#include <stdio.h>
int main(void) {
int a[5] = {1, 2, 3, 4, 5};
int* ptr1 = (int*)(&a + 1);
int* ptr2 = (int*)((int)a + 1);
printf("%x, %x\n", ptr1[-1], *ptr2);
}
这个题目主要是考了两个知识点一个是指针的知识,第二个是大端机和小端机的知识
首先需要明确x86是小端机,所以它的数值在各个字节中的顺序是从小到大的
比如对于int型的数值其在内存中的编码就是 1 0 0 0
在解释清楚这一点后,正式的解析下这道题目
int* ptr1 = (int*)(&a + 1);
&a 对数组名进行取地址,数组名所代表的是一个有5个int元素的数组,所以&a代表的就是一个代表有五个元素的数组的指针
所以这里的(&a + 1)实际上就是取得了a[4]也就是数字5后面的地址,这样又将其转换为一个int*指针,此时的ptr1就是一个指向
a[5]后地址的int型指针,ptr1[-1]其实就等价于*(ptr1-1)这样的运算,所以ptr1-1得到的就是a[4]的地址所以得出的第一个值就是a[4]的值
也就是5.
接下来再对第二个指针进行分析,(int)将一个指针值转换为了int值,(int)a+1就是a的地址值加上1,a是int*类型的所以a+1的话其值实际上
了4,而现在将a转换为int型的所以这样就相当于给其值加上1,这个的作用效果和(char*)a +
1是相同的.然后这里又将该值转换为一个int*类型
的指针,所以当使用*ptr2的时候就会取四个字节,并读取出其中的值.
因为是小端机所以1在4个字节中的分布是0x01 0x00 0x00 0x00, 2在4个字节中的分布是 0x02 0x00 0x00 0x00
此时ptr2指向的是a中的第二个字节所在的地址,所以当取4个字节时实际取到的是 0x00 0x00 0x00
0x02这样当将其解释出真是的值实际是
0x02 0x00 0x00 0x00 这里的输出使用的是%x所以输出的是十六进制的数字,所以输出了2000000.