数组名转指针实验遇意外输出:为何两次打印均为地址?
数组名与指针的疑惑:为何两次输出都是地址?
你的代码:
#include<stdio.h> int main() { int a[] = {1, 2, 3, 4, 5, 6}; printf("%d\n",*(&a+1)); printf("%d\n",**(&a+1)); return 0; }
运行输出:
6422304 6422284
你预期第一个输出是地址,第二个是该地址的数值,但实际都是地址,问题出在这几个核心点:
1. 先明确&a的类型
a是长度为6的int数组,&a的类型是指向int[6]数组的指针(记作int (*)[6])。这种指针的移动步长是整个数组的大小(假设int占4字节,步长就是6*4=24字节),和普通int指针的步长(4字节)完全不同。
2. &a+1的指向
给&a加1时,指针会向后移动一个整个数组的长度,最终指向数组a末尾之后的第一个位置(等价于a+6的地址)。
3. *(&a+1)的本质
解引用&a+1得到的是int[6]类型的数组,但在传给printf这类函数时,数组类型会自动退化为指向其第一个元素的指针(也就是int*类型),这个指针指向的就是a数组末尾之后的地址。你用%d打印这个指针,本质是把指针的内存地址值以十进制整数输出,所以第一个输出是地址的数值。
4. **(&a+1)为何也输出地址?
首先*(&a+1)退化为int*指针,再解引用一次理论上应该访问该指针指向的内存值,但这里有两个关键问题:
- 你用错了格式符:
%d用于打印int类型,但**(&a+1)访问的是数组a之外的内存,属于未定义行为——编译器不会按你预期的逻辑处理。 - 你的输出呈现为地址,大概率是编译器内存布局或优化导致的异常结果,这个操作本身就是非法的,结果完全不可靠。
正确的写法示例
如果想打印地址,要用%p格式符;如果要合法访问数组元素,不能越界:
#include<stdio.h> int main() { int a[] = {1, 2, 3, 4, 5, 6}; // 打印&a+1的数组指针地址 printf("%p\n", &a+1); // 打印*(&a+1)退化成的指针地址(和上面地址值一致) printf("%p\n", *(&a+1)); // 打印数组最后一个元素的合法值 printf("%d\n", a[5]); return 0; }
内容的提问来源于stack exchange,提问作者Mahmoud Hamed
相关产品推荐
相关产品推荐

