这是由一道面试题联想到的一些问题,这里自己给做个小总结!
#include <stdio.h>
int main() {
int a[5] = { 1, 2, 3, 4, 5 };
int *pi = &a + 1;
printf("%d, %d\n", *(a + 1), *(pi - 1));
return 0;
}
答案是2, 5。至于是为什么,我后面说一下我自己的理解。
这里有个要注意的地方,以上代码在CodeBlock中会有个警告,但是在VS2013中有个错误提示,错误如下:”int()[5]类型的值不能用于初始化”int“类型的实体。当然,这里我们可以进行强制类型转换,那么这个错误提示就会消失。修改后的代码如下:
#include <stdio.h>
int main() {
int a[5] = { 1, 2, 3, 4, 5 };
int *pi = (int *)(&a + 1);
printf("%d, %d\n", *(a + 1), *(pi - 1));
return 0;
}
这个时候,再编译运行就得到了我们的正确答案2, 5。
我个人对于结果的理解分析:变量a指向的整个数组的首地址,那么变量a每次加1就移动4个字节(相当于从指向第1个数位置移动到指向第2个数);对变量a再进行取地址操作,那么&a每次加1就移动4*5个字节(相当于从指向当前数组首地址位置移动到指向下一个数组首地址位置)。大概示意图如下:
#include <stdio.h>
int main() {
//a是一个二维数组
int a[2][3];
/* 1、a的类型是int(*)[2][3],a的值是指向数组第1个元素地址。
** 2、&a的类型是int*, &a的值是指向整个数组的首地址。
** 3、a的字节数是4*6, &a的字节数是4。
*/
printf("a = %x, &a = %x\n", a, &a);
printf("sizeof(a) = %d, sizeof(&a) = %d\n", sizeof(a), sizeof(&a));
printf("a + 1 = %x, &a + 1 = %x\n", a + 1, &a + 1);
/* 1、a[0]的类型是int(*)[3], a[0]的值是指向数组第1行元素第1个元素的地址。
** 2、&a[0]的类型是int*, &a[0]的值是指向数组第1行整行元素的首地址。
** 3、a[0]的字节数是4*3, &a[0]的字节数是4。
*/
printf("a[0] = %x, &a[0] = %x\n", a[0], &a[0]);
printf("sizeof(a[0]) = %d, sizeof(&a[0]) = %d\n", sizeof(a[0]), sizeof(&a[0]));
printf("a[0]+1 = %x, &a[0] + 1 = %x\n", a[0] + 1, &a[0] + 1);
}
运行结果如下:
从结果我们可以看到,a,&a,a[0],&a[0]地址值都是一样的,不过由于变量的类型不一样,所以每次移动的值也一样。