C++数组名称含义解析及代码输出结果疑问
你这个问题问到了C++(C语言里也是同样逻辑)里数组名的经典“迷惑点”——数组名在不同场景下的含义并非完全一致,不能简单等同于指针。咱们结合你的代码和疑问逐个拆解:
先明确这段代码在64位系统下的实际输出(假设int占4字节):
- Line1:输出第一个元素
arr[0]的内存地址(比如0x7ffeefbff560) - Line2:输出的地址数值和Line1完全相同,但背后的含义截然不同
- Line3:输出
20(5个int × 4字节/个) - Line4:输出
8(64位系统下指针的固定大小;32位系统会是4)
接下来逐个分析每一行的逻辑:
核心规则:数组名的两种身份
数组名在绝大多数场景下会隐式转换为指向第一个元素的指针(也就是你理解的arr = &arr[0]),但有两个关键例外:
- 当它作为
sizeof的操作数时 - 当它作为
&(取地址运算符)的操作数时
Line1:cout<<arr<<endl;
这里属于“绝大多数情况”,数组名arr自动转换成了指向第一个元素的int*类型指针,所以输出的就是&arr[0]的地址,和你的预期完全一致。
Line2:cout<<&arr<<endl;
这里触发了第二个例外:&arr取的是整个数组的地址,它的类型是int (*)[5](读作“指向包含5个int的数组的指针”)。
虽然它的地址数值和&arr[0]完全重合,但两者的类型差异极大:
- 对
arr(即int*)做arr + 1,指针会向后移动4字节(一个int的大小),指向arr[1] - 对
&arr(即int (*)[5])做&arr + 1,指针会向后移动20字节(整个数组的大小),直接跳到数组末尾之后的内存位置
你的预期里说“会输出arr[0]的地址”,从数值上看没错,但本质上它是整个数组的起始地址,只是刚好和第一个元素的起始地址重合而已。
Line3:cout<<sizeof(arr)<<endl;
这里触发了第一个例外:sizeof(arr)计算的是整个数组的字节大小,而非指针的大小。5个int每个4字节,所以结果是5×4=20,这也是它和sizeof(&arr)结果不同的原因。
Line4:cout<<sizeof(&arr)<<endl;
&arr是一个指针类型(不管它指向的是数组还是单个元素),在64位系统下所有指针的大小都是8字节,32位系统是4字节,所以这里输出的是指针本身的大小。
总结一下:数组名不是“天生就是指向第一个元素的指针”,它本质上是数组的名字,只是大多数场景下会被隐式转换为指针使用;只有在sizeof和&面前,它才会暴露自己“代表整个数组”的真实身份。
内容的提问来源于stack exchange,提问作者Embedded_Dude

