题目一:
int main()
{
int a[4] = { 1, 2, 3, 4 };
int* ptr1 = (int*)(&a + 1);
int* ptr2 = (int*)((int)a + 1);
printf("%x,%x\n", ptr1[-1], *ptr2);
return 0;
}
解析:
&a+1:&a是取出整个数组地址,&a+1是跳过整个数组;
(int*)(&a + 1):再强制转化成整形指针,指向数组最后;
(int)a + 1:a是首元素地址(假如地址是 1040ff10),强制转化成整形为十进制位 272695056,再加1等于272695056;
(int*)((int)a + 1):再把得出的十进制强制转化成整形指针为 1040ff11,指向原地址向后一个字节;
结果:用16进制打印
ptr[-1]:*(ptr1-1)把ptr1指针向后移动一个单位此时指向a[3];
*ptr2:直接解引用向后访问4个字节;
题目二:
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
解析:
a表示为二维数组地址,a的类型为int (*)[5];和p的类型不一致;但也可以强行赋值。
两地址相减等于元素个数;
相减为-4,内存中以二进制补码存储;
原码:10000000 00000000 00000000 00000100
反码:11111111 11111111 11111111 11111011
补码:11111111 11111111 11111111 11111100
%d是以整形打印,补码首位为1,表示负数,要先转化为原码,如上还是打印-4,
%p是打印地址,以16进制、补码形式打印
作者会持续更新