数组名和指针有相似之处,但数组名并不是指针。以下是关键区别和联系:
1. 数组名是“常量指针”吗?
数组名代表数组首元素的地址(类型为 T*,T 是元素类型),但它是不可修改的常量(即不能重新赋值)。
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr; // 正确:数组名隐式转换为首元素地址
arr = p; // 错误!数组名不能重新赋值(不是左值)
指针是变量,可以指向其他地址:
int *p = arr;
p++; // 合法:指针可以移动
2. 关键区别
|
特性 |
数组名 |
指针 |
|
本质 |
数组的标识符 |
存储地址的变量 |
|
赋值操作 |
不可修改(非左值) |
可以修改 |
|
|
返回整个数组的大小 |
返回指针本身的大小 |
|
|
返回数组的地址( |
返回指针变量的地址 |
示例:sizeof 的区别
int arr[5];
int *p = arr;
printf("%zu\n", sizeof(arr)); // 输出 20(假设 int 占 4 字节)
printf("%zu\n", sizeof(p)); // 输出 4 或 8(指针大小)
示例:& 操作的区别
printf("%p\n", &arr); // 类型是 int(*)[5](指向数组的指针)
printf("%p\n", &p); // 类型是 int**(指向指针的指针)
3. 数组名何时退化为指针?
在大多数表达式中,数组名会隐式转换为首元素地址(即“退化”为指针),例如:
函数传参时(实际传递的是指针):
void foo(int *p);
foo(arr); // 数组名退化为指针
参与算术运算时:
arr + 1; // 合法,等价于 &arr[1]
但以下情况不会退化:
- 使用
sizeof(arr)。 - 使用
&arr(获取的是数组的地址,而非首元素地址)。
4. 多维数组的情况
对于多维数组(如 int arr[2][3]):
arr的类型是int[2][3],退化为int(*)[3](指向一维数组的指针)。arr[i]退化为int*(指向元素的指针)。
总结
- 数组名不是指针,但在大多数情况下会隐式转换为指针。
- 数组名是编译时的常量符号,代表一块连续内存的标识符;指针是运行时变量,存储地址。
- 理解这一区别有助于避免错误(如错误的
sizeof或指针运算)。
如果需要进一步操作(如动态分配数组),通常需要使用指针(如 malloc)。
1964

被折叠的 条评论
为什么被折叠?



