C语言静态数组指针运算疑问:&a与a地址相同为何解引用结果不同?
C语言静态数组指针运算疑问解答
先看你提供的代码和运行输出:
代码
#include <stdlib.h> #include <stdio.h> void main() { int N=3, a[N]; for (int i=0; i<N; i++) a[i] = 1000+i; printf("&a = %p\n",&a); printf("a = %p\n",a); printf("*a = %d\n",*a); printf("*(&a) = %d (as an int)\n",*(&a)); printf("*(&a) = %p (as a pointer)\n",*(&a)); }
运行输出
&a = 0x7ffee9043ae0 a = 0x7ffee9043ae0 *a = 1000 *(&a) = -319989024 (as an int) *(&a) = 0x7ffee9043ae0 (as a pointer)
核心疑问解答:为什么&a和a的地址值完全相同?
这是因为数组的起始地址和它首元素的起始地址是同一个内存位置:
a作为数组名,在大多数表达式场景中会隐式转换为指向数组首元素的指针(类型为int*),它指向的是a[0]的起始地址。&a是整个数组的地址,类型为int(*)[3](指向包含3个int元素的数组的指针),它指向的是整个数组的起始位置,而数组的起始位置正好就是首元素a[0]的起始位置。
两者指向的内存起点完全一致,所以用%p打印时,地址值自然相同,但它们的类型本质完全不同——这也是*a和*(&a)结果不同的根本原因。
补充:*a和*(&a)的差异解析
*a:因为a转换为int*,解引用后得到的是首元素a[0]的值,也就是1000,类型是int,用%d打印正常。*(&a):&a是int(*)[3]类型,解引用后得到的是数组a本身(类型为int[3]),而数组名又会再次转换为指向首元素的指针(int*)。当你用%d打印这个指针时,是把指针的地址值当成int类型来解析(由于指针和int的字节长度、存储方式可能不同,就出现了奇怪的负数);用%p打印时,就是正确的首元素地址。
另外纠正一个误区:你之前认为&a是int**类型是错误的,&a的类型是指向数组的指针,不是指向指针的指针。
内容的提问来源于stack exchange,提问作者PierU
相关产品推荐
相关产品推荐

