[英]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;
}
the output is 2 5 . 输出为2 5 。 &a
means the address of a[0]
so &a+1
should be the address of a[1]
. &a
表示a[0]
的地址,因此&a+1
应该是a[1]
的地址。 So ptr
should hold the address of a[1]
. 因此, ptr
应该保留a[1]
的地址。 *(a+1)
will be 2 but *(ptr-1)
should also be 2. I can't understand how is it printing 5. *(a+1)
将为2,但*(ptr-1)
也将为2。我不知道它如何打印5。
This expression is the important thing: &a+1
. 此表达式很重要: &a+1
。 That is actually (&a)+1
which is equal to (&a)[1]
which will be a pointer to one element past the end of the array. 实际上是(&a)+1
等于(&a)[1]
,它将是指向数组末尾一个元素的指针。
If we look at it more "graphically" it looks like this, with relevant pointers added: 如果我们更“图形化地”看待它,它看起来像这样,并添加了相关的指针:
+------+------+------+------+------+ | a[0] | a[1] | a[2] | a[3] | a[4] | +------+------+------+------+------+ ^ ^ ^ | | | | &a[1] (equal to *(a + 1)) | | | &a[0] (equal to a) | | | &a &a+1
First of all, the type of &a
is int (*)[5]
, so your cast to int *
will break strict aliasing (which leads to undefined behavior ). 首先, &a
的类型是int (*)[5]
,因此您对int *
的强制转换将破坏严格的别名(这将导致未定义的行为 )。
Second of all, since ptr
is pointing, effectively, to what would be a[5]
then ptr - 1
will point to a[4]
. 第二,由于ptr
有效指向a[5]
因此ptr - 1
将指向a[4]
。
&a
is not the address of a[0]
but the address of a
. &a
不是的地址a[0]
的,但地址a
。 The values may be the same but the types are different. 值可以相同,但类型不同。 That is important when it comes to pointer arithmetic. 对于指针算术,这一点很重要。
In the expression &a + 1
, you first have &a
which has type int (*)[5]
, ie a pointer to an array of size 5. When you add 1 to that it actually adds sizeof(a)
bytes to the pointer value. 在表达式&a + 1
,首先具有类型为int (*)[5]
&a
,即指向大小为5的数组的指针。当向其添加1时,它实际上将sizeof(a)
个字节添加到指针值。 So &a + 1
actually points to one byte past the end of the array. 所以&a + 1
实际上指向数组末尾的一个字节。 You then cast this expression from int (*)[5]
to int *
and assign it to ptr
. 然后,您将此表达式从int (*)[5]
为int *
并将其分配给ptr
。
When you then evaluate *(ptr - 1)
, the -
operator subtracts 1 * sizeof(int)
from the byte value of ptr
so it now points to the last element of the array, ie 5, and that is what is printed. 然后,当您对*(ptr - 1)
求值时, -
运算符从ptr
的字节值中减去1 * sizeof(int)
,因此它现在指向数组的最后一个元素,即5,这就是要打印的内容。
&a
gives the address of the array as an array pointer , int (*)[5]
. &a
将数组的地址作为数组指针 int (*)[5]
。 It is a pointer type that points at the array as whole, so if you do pointer arithmetic with it, +1
will mean +sizeof(int[5])
which is not what you intended. 它是一种指向整个数组的指针类型,因此,如果对它进行指针算术运算,则+1
表示+sizeof(int[5])
,这不是您想要的。
Correct code: 正确的代码:
int *ptr = a+1;
Notably, the cast (int*)
was hiding this bug. 值得注意的是,强制转换(int*)
隐藏了该错误。 Don't use casts to silence compiler errors you don't understand! 不要使用强制转换使您不了解的编译器错误消失!
Firstly, you said: &a
means the address of a[0]
so &a+1
should be the address of a[1] ? 首先,您说: &a
表示a[0]
的地址,所以&a+1
应该是a [1]的地址? No you are wrong. 不,你错了。 &a
means address of a
not a[0]
. &a
的装置地址a
不a[0]
And &a+1
means it increments by whole array size not just one elements size and a+1
means address of a[1]
. &a+1
表示它以整个数组的大小递增,而不仅仅是一个元素的大小,而a+1
表示a[1]
地址。
Here 这里
int a[5] = {1,2,3,4,5};
lets assume base address of a
is 0x100
让我们假设基址的a
是0x100
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 ..
LSB
|
a
When you are doing 当你做的时候
int *ptr = (int*)(&a+1);
Where ptr
points ? ptr
点在哪里? first (&a+1)
performed and it got increments by whole array size ie 首先执行(&a+1)
,它的增量是整个数组的大小,即
(&a+1) == (0x100 + 1*20) /* &a+1 here it increments by array size */
== 0x120
So now ptr
points to 所以现在ptr
指向
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 0x120
a |
ptr points here
Now when you print like 现在,当您打印像
printf("%d %d", *(a+1), *(ptr-1));
Here 这里
*(a+1) == *(0x100 + 1*4) /* multiplied by 4 bcz of elements is of int type*/
== *(0x104) /* value at 0x104 location */
== 2 (it prints 2)
And 和
*(ptr-1) == *(0x120 - 1*4)
== *(0x116) /* prints value at 0x116 memory location */
== 5
Note :- Here 注意:-这里
int *ptr = (int*)(&a+1);
type of &a
is of int(*)[5]
ie pointer to an array of 5 elements but you are casting as of int*
type, as pointed by @someprogrammerdude it breaks the strict aliasing and lead to undefined behavior. &a
类型为int(*)[5]
即指向5个元素的数组的指针,但是您要转换为int*
类型,如@someprogrammerdude所指出的那样,它破坏了严格的别名并导致未定义的行为。
Correct one is 正确的是
int *ptr = a+1;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.