[英]strange output issue in c
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。
此表达式很重要: &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]
。
&a
不是的地址a[0]
的,但地址a
。 值可以相同,但类型不同。 对于指针算术,这一点很重要。
在表达式&a + 1
,首先具有类型为int (*)[5]
&a
,即指向大小为5的数组的指针。当向其添加1时,它实际上将sizeof(a)
个字节添加到指针值。 所以&a + 1
实际上指向数组末尾的一个字节。 然后,您将此表达式从int (*)[5]
为int *
并将其分配给ptr
。
然后,当您对*(ptr - 1)
求值时, -
运算符从ptr
的字节值中减去1 * sizeof(int)
,因此它现在指向数组的最后一个元素,即5,这就是要打印的内容。
&a
将数组的地址作为数组指针 int (*)[5]
。 它是一种指向整个数组的指针类型,因此,如果对它进行指针算术运算,则+1
表示+sizeof(int[5])
,这不是您想要的。
正确的代码:
int *ptr = a+1;
值得注意的是,强制转换(int*)
隐藏了该错误。 不要使用强制转换使您不了解的编译器错误消失!
首先,您说: &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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.