下面这段代码输出什么?
int main()
{
int a[5] = { 1,2,3,4,5 };
int *p = (int *)(&a + 1);
printf("%d,%d\n", *(a + 1), *(p - 1));
return 0;
}
1.定义a
int a[5] = { 1, 2, 3, 4, 5 }; a是一个大小为5的数组
2.弄清楚&a究竟是什么
int *p = (int *)(&a + 1); 这一句非常绕。
分析a和&a的意义
首先如果你打印一下:a和&a, 会发现它们会输出同一个地址。但其实a和&a是不同的,a是数组首地址,也就是a[0]的地址;而&a是整个数组对象的首地址,这是两个意义。
因此,(a+1)中,a是a[0]元素地址,系统会认为+1是再加一个元素的大小,所以a+1是数组下一个元素的地址,也就是a[1]的地址,打印*(a+1),输出2。
而&a+1中,&a是一个数组对象的地址,那&a为什么能表示一个数组对象的地址呢,原因在于&a的类型是int*[5],是一个指针类型的数组,其中的&a[i]是一个指针,存储了a[i]的地址,比如&a[1]是a[1]的地址,所以*(&a[1])=a[1]=*(a+1)=2。所以&a+1中,系统会认为+1是再加一个数组的大小,所以&a+1是下一个数组的地址,也就是a[5]的地址。
3.强制转换为int*
再来分析(int *),它把(&a+1)强制转换为(int *)类型,那么&a+1原来是什么类型呢?是int*[5]类型,强制转换为(int*)后,(int *)(&a + 1)就是一个int*类型的指针了,指向a[5]. 所以p是一个指向a[5]的int*指针。
4.p-1的运算
所以我们再来看p-1:
p是一个int*型变量,所以它的大小就是一个int*型,那么p-1中,系统会认为减1是减去一个int*型的大小,所以p-1就是一个指向a[4]的指针。
搞清楚原理后,不太重要的结果
输出2,5