一、数组与指针的关系
-
&a[0] = a
数组名a
在表达式中退化为指向首元素的指针,&a[0]
获取的是数组第一个元素的地址,等价于a
。 -
a[0] = \*a
首元素的值可通过下标a[0]
或指针解引用*a
访问,二者等价。
二、sizeof
运算符
-
sizeof
是运算符而非函数,计算类型或对象占用的内存大小。 -
语法示例:
int a[10]; sizeof(a); // 计算整个数组的大小(40字节,假设int为4字节) sizeof(a[0]); // 计算单个元素的大小
三、数组初始化规则
数组元素的初始值取决于其存储类型:
类型 | 存储位置 | 初始化值 |
---|---|---|
局部变量数组 | 栈 | 未初始化(垃圾值) |
全局变量数组 | 数据段 | 自动初始化为0 |
静态局部变量数组 | 数据段 | 自动初始化为0 |
四、数组声明的注意事项
-
数组大小必须为常量表达式
-
错误示例:
int n = 10; int arr[n];
(C99 前非法,C11 中为可选特性) -
正确做法:使用宏或枚举定义常量。
#define SIZE 10 int arr[SIZE];
-
五、指定初始化器(C99特性)
int count[4] = { [2] = 3 }; // count[2] 初始化为3,其他元素为0
六、字符数组 vs 字符指针
类型 | 示例 | 存储位置 | 可修改性 |
---|---|---|---|
字符数组 | char str[20] = "hello" | 栈 | 可修改内容 |
字符指针 | char *p = "hello" | 只读数据段 | 不可修改内容 |
七、函数参数传递
-
scanf("%d", &i)
中必须使用&
符号,因为scanf
需要变量的地址(值传递机制下需显式传递指针)。 -
对比数组传参:数组名本身是地址,无需
&
:c
复制
int arr[10]; scanf("%d", arr); // 等价于 &arr[0]
关键总结
-
数组名在多数情况下退化为指针,但
sizeof(a)
会计算整个数组的大小。 -
未初始化的局部数组包含垃圾值,全局/静态数组自动初始化为0。
-
数组大小应使用常量表达式定义,避免依赖编译器的变长数组支持。
-
字符串字面量赋值给指针时不可修改,字符数组可读写。