地址&a和首地址&a[0]的区别
main(){ long a[4] = {1, 2, 3, 4}; long *p1=(long *)(&a+1); // long *p1=(&a+1);//整个数组地址的下一个long数组的首地址,即存储整个数组a的最后一个字节的下一个字节内存的地址 // long *p1=(&a[0]+1);//数组第1个元素地址的下一个long的元素首地址,即数组第2个元素的首地址 // long *p1=(long*)(&a[0]+1);//同上 long *p2=(long *)((long)a+1); printf("%lx\n", p1[-1]); printf("%lx\n", *p2); }
(&a+1)和(&a[0]+1)中的1不同,前者的是整个数组的长度,后者是数组元素数据类型的长度
首先
long *p1=(long *)(&a+1);
&a是整个数组的地址,因此&a+1实际上是向后偏移了16个字节,因此 p1 指向了数组边界。然后输出 p1[-1] 等价于 *(p1-1),因为 p1 是 long 型指针,因此 p1-1 就向前偏移 sizeof(long) 个字节,也就是指向了 a[3]。
其次
long *p2=(long *)((long)a+1);
(long)a+1 是一个纯整数运算(因为a被强转为long了),因此 p2 就指向了long型数据 a[0] 的第二个字节,最后打印 *p2 时,由于 p2 是一个 long 型指针,系统会从 a[0] 的第二个字节开始,取出 sizeof(long) 个字节出来作为 long 型数据来解释,因此最后输出的结果是 a[0] 的高位三字节和 a[1] 低位一字节的数据。