1) #include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
int *ptr = (int*)(&a+1);
printf("%d %d", *(a+1), *(ptr-1));
return 0;
}
输出为2 5 。 &a
的意思是a[0]
的地址,因此&a+1
应该是a[1]
的地址。因此ptr
应该保留a[1]
的地址。 *(a+1)
将为2,但*(ptr-1)
也将为2。我不知道它如何打印5。
答案 0 :(得分:4)
此表达式很重要:&a+1
。实际上是(&a)+1
等于(&a)[1]
,它将是指向数组末尾一个元素的指针。
如果我们更“图形化”地看待它,它看起来像这样,并添加了相关的指针:
+------+------+------+------+------+ | a[0] | a[1] | a[2] | a[3] | a[4] | +------+------+------+------+------+ ^ ^ ^ | | | | &a[1] (equal to *(a + 1)) | | | &a[0] (equal to a) | | | &a &a+1
首先,&a
的类型为int (*)[5]
,因此对int *
的强制转换将破坏严格的别名(导致未定义的行为)。
第二,由于ptr
有效指向a[5]
,因此ptr - 1
将指向a[4]
。
答案 1 :(得分:2)
&a
不是a[0]
的地址,而是a
的地址。值可以相同,但类型不同。对于指针算术,这一点很重要。
在表达式&a + 1
中,首先具有类型为&a
的{{1}},即指向大小为5的数组的指针。当您向其添加1时,它实际上将添加{{ 1}}个字节到指针值。因此int (*)[5]
实际上指向数组末尾的一个字节。然后,您将此表达式从sizeof(a)
强制转换为&a + 1
并将其分配给int (*)[5]
。
当您随后计算int *
时,ptr
运算符从*(ptr - 1)
的字节值中减去1 * -
,因此它现在指向数组的最后一个元素,即5,那就是打印的内容。
答案 2 :(得分:1)
&a
给出数组的地址,作为 array指针,int (*)[5]
。这是一种指向整个数组的指针类型,因此,如果对它进行指针算术运算,+1
的意思是+sizeof(int[5])
,这不是您想要的。
正确的代码:
int *ptr = a+1;
值得注意的是,演员(int*)
隐藏了这个错误。不要使用强制转换使您不了解的编译器错误消失!
答案 3 :(得分:1)
首先,您说过: &a
表示a[0]
的地址,因此&a+1
应该是a [1]的地址?不,您错了。 &a
表示a
而不是a[0]
的地址。 &a+1
表示它以整个数组大小递增,而不仅仅是一个元素的大小,而a+1
表示a[1]
的地址。
这里
int a[5] = {1,2,3,4,5};
让a
的基地址为0x100
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 ..
LSB
|
a
做事时
int *ptr = (int*)(&a+1);
ptr
指向何处?首先执行(&a+1)
,它按整个数组大小递增,即
(&a+1) == (0x100 + 1*20) /* &a+1 here it increments by array size */
== 0x120
所以现在ptr
指向
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 0x120
a |
ptr points here
现在,当您进行打印时
printf("%d %d", *(a+1), *(ptr-1));
这里
*(a+1) == *(0x100 + 1*4) /* multiplied by 4 bcz of elements is of int type*/
== *(0x104) /* value at 0x104 location */
== 2 (it prints 2)
和
*(ptr-1) == *(0x120 - 1*4)
== *(0x116) /* prints value at 0x116 memory location */
== 5
注意:-此处
int *ptr = (int*)(&a+1);
&a
的类型是int(*)[5]
的指针,即指向5个元素的数组的指针,但是您要转换为int*
类型的指针,如@someprogrammerdude所指出的那样,它破坏了严格的别名并导致发生不确定的行为。
正确的是
int *ptr = a+1;