C++中数组与sizeof()的疑问:数组名是否为指针?
数组名与指针退化的核心问题解答
核心结论先明确
数组名不是普通指针,但在绝大多数场景下会被C语言隐式转换为指向数组首元素的指针(也就是常说的“退化”)。只有少数例外场景中,数组名会保留原有的数组类型,这就是你看到sizeof结果差异的根本原因。
问题1:数组名并非指向首元素的指针?那它是什么?为何支持指针算术?
- 数组名是数组类型的标识符。比如定义
int arr[5];,arr的实际类型是int[5](包含5个int元素的数组),而非int*(指向int的指针)。 - 你能对数组名做指针算术(比如
arr+1)或下标访问(arr[i]),本质是C标准的规定:当数组名出现在表达式中(除特殊场景外),会自动转换为指向首元素的指针。转换后arr+i等价于&arr[i],arr[i]自然等价于*(arr+i)——看起来像是数组名本身支持这些操作,实则是转换后的指针在起作用。
问题2:数组名确实是首元素指针?那为何与退化后的指针存储的信息不同?
- 数组名不是首元素指针,只是会被隐式转换。而
sizeof(arr)就是不会触发退化的例外场景之一:当数组名作为sizeof的操作数时,它保持原有数组类型,因此sizeof(arr)计算的是整个数组的总字节数(比如5个int元素就是5*sizeof(int))。 - 当数组作为函数参数传递时,C标准会强制将参数的数组类型调整为指针类型。比如
void func(int arr[5])会被编译器自动解析为void func(int* arr),此时函数内部的arr就是普通指针,sizeof(arr)返回的自然是指针大小(64位机器上为8字节)。 - 除了
sizeof,还有两个常见的非退化场景:- 数组名作为
&的操作数时:&arr得到的是指向整个数组的指针(类型为int (*)[5]),而非指向首元素的指针(虽然两者内存地址值相同,但类型不同,指针算术的行为也不一样)。 - 用字符串字面量初始化字符数组时:
char str[] = "hello";中的str保持数组类型,sizeof(str)会返回包含终止符的总字节数(6字节)。
- 数组名作为
代码示例验证
#include <stdio.h> void test(int arr[5]) { // 函数内arr已退化为指针,64位机输出8 printf("函数内sizeof(arr):%zu\n", sizeof(arr)); } int main() { int arr[5] = {1,2,3,4,5}; // 主函数内arr保持数组类型,输出20(假设int为4字节) printf("主函数内sizeof(arr):%zu\n", sizeof(arr)); // arr转换为指向首元素的指针,地址与&arr[0]相同 printf("arr(首元素指针):%p\n", arr); // &arr是指向整个数组的指针,地址值相同但类型不同 printf("&arr(数组指针):%p\n", &arr); test(arr); return 0; }
内容的提问来源于stack exchange,提问作者Kotaka Danski
相关产品推荐
相关产品推荐

