int main()
{
int a[5]={1,2,3,4,5};
int *ptr1=(int*)(&a+1);
int *ptr2=(int*)((int)a+1);
printf("%x,%x",ptr1[-1],*ptr2);
return 0;
}
00000000 :01 00 00 00 02 00 00 00
00000008 :03 00 00 00 04 00 00 00
00000010 :05 00 00 00
由于a的值 就是00000000 但是对a=a+1 之后 a会变成 00000004,因为加的是1*sizeof(int)个字节,但是把a强制类型转换成int之后就编变成 数值 00000000 了,不在有地址的任何附加属性,对其进行+1 操作也是 纯粹数学上的加1 变成00000001
(int*)((int)a+1)之后指向 00 00 01 00 00 00 02
结果便是10000
{
int a[5]={1,2,3,4,5};
int *ptr1=(int*)(&a+1);
int *ptr2=(int*)((int)a+1);
printf("%x,%x",ptr1[-1],*ptr2);
return 0;
}
第一个输出的是5
a是一个数组名,那么&a表示整个数组的指针,它的值和数组a首元素的地址值一样,但是这个指针指向的内存大小是整个数组的总大小。那么&a+1表示的就是整个数组a最后一个元素的下一个内存单元开始数组指针,再把这个指针转换成int的指针,那么ptrl就指向了数组a最后一个元素之后下一个内存开始的4个字节(int*)内存。
ptr1[-1]被解析成*(ptr1-1),即ptr1往后退4个字节,指向a[4],因此其值为5.
注意:虽然&a与a的值都是数组的首地址,但是&a+1 指向下一个数组的首地址,a+1指向数组下一个元素a[1]的首地址
第二个的输出 在不同的cpu上结果是不一样的
(int)a+1 :将数组a 的首地址转换成int并加1,指向a[0]的第二个字节的地址,然后将这个地址转换成 int * 型赋值给ptr2,也就是说ptr2的值是a[0]第二个字节后的连续四个字节的值。
00000000 :01 00 00 00 02 00 00 00
00000008 :03 00 00 00 04 00 00 00
00000010 :05 00 00 00
由于a的值 就是00000000 但是对a=a+1 之后 a会变成 00000004,因为加的是1*sizeof(int)个字节,但是把a强制类型转换成int之后就编变成 数值 00000000 了,不在有地址的任何附加属性,对其进行+1 操作也是 纯粹数学上的加1 变成00000001
此时又强制类型转换成(int*) 那么此时指向的内存内容是 00 00 00 02 00 00 00
对其取内容(以%x的方式取,取4个字节) 取出来 是00 00 00 02 ,这个按16进制解释出来就是 2000000
大端存储大同小异:内存布局 00 00 00 01 00 00 00 02(int*)((int)a+1)之后指向 00 00 01 00 00 00 02
结果便是10000