英文:
Unexpected behaviour while referencing and dereferencing array with pointer
问题
这是代码:
int a[5] = { 1, 2, 3, 4, 5 };
int* p = (int*)(&a + 1);
printf("%d, %d", (*a+1), *(p - 1));
// 输出结果 2, 5
因为我相信 p
指向数组 a
的第二个元素,即 2。所以 *(p-1)
的输出应该是 1。但在 VS 中,*(p-1)
输出为 5,原因是什么?谢谢帮助!
我认为输出应该是 2, 1。
英文:
Here is the code:
int a[5] = { 1, 2, 3, 4, 5 };
int* p = (int*)(&a + 1);
printf("%d, %d", (*a+1), *(p - 1));\
// output 2, 5
As I believe p
points the second element in array a
, which is 2. So the output of *(p-1)
is 1.
But in VS *(p-1)
output 5, what is the reason?
Thanks for helping!
I believe the output should be 2, 1.
答案1
得分: 4
答案在你插入(int*)
强制类型转换以覆盖编译器更好判断之前,你(可能)看到的错误消息中:
int* p = (&a + 1);
temp.cpp:7:10: error: cannot initialize a variable of type 'int *' with an rvalue of type 'int (*)[5]'
int * q = &a;
因为a
的类型是int[5]
,这意味着&a
的类型是指向int[5]
的指针,并且这也意味着sizeof(a)
等于5*sizeof(int)
... 这意味着(&a+1)
指向数组结束后的地址(也就是如果你有一个由多个包含5个整数的数组组成的数组,它指向下一个数组的开头),而不是你数组中的第二个int
。
所以,当你在你的代码中评估*(p-1)
时,你得到一个指向&a[5]
(虽然它不存在,但不要紧)的指针,然后减去1个int
,得到一个指向&a[4]
的指针,然后解引用它,从你的数组中获取值5
。
英文:
The answer to your question lies in the error message that you (probably) saw just before you inserted the (int*)
cast to override the compiler's better judgement:
int* p = (&a + 1);
temp.cpp:7:10: error: cannot initialize a variable of type 'int *' with an rvalue of type 'int (*)[5]'
int * q = &a;
Since a
is of type int[5]
, that means that &a
is of type pointer-to-int[5]
, and also it means that sizeof(a)
is equal to 5*sizeof(int)
... which means that (&a+1)
is pointing to the address after the end of the array (i.e. where the next array-of-5-ints would be if you had an array of arrays-of-5-ints-each), not to the second int
in your array.
So when you evaluate *(p-1)
in your code, you are taking a pointer to &a[5]
(which doesn't exist, but nevermind that) and then subtracting 1 int
from it, which gives you a pointer to &a[4]
, which you dereference to get the value 5
from your array.
答案2
得分: 0
问题出在数组的标识符(变量a),即a存储了数组起始位置的指针。
你写了(&a + 1),所以它将整个数组视为指针,+1指向数组大小之后的下一个位置。
例如,数组的地址为100, 104, 108, 112, 116
&a+1 -> 120
请使用a+1而不是&a+1
a+1 -> 104
因此,新的代码将是:
int a[5] = { 1, 2, 3, 4, 5 };
int* p = (int*)(a + 1);
printf("%d, %d", (*a+1), *(p - 1));
这将给出期望的输出2,1。
希望这能够解决疑惑。
另外,要说的是int *a和int a[]在指针方面有些相似,但不完全相同。
英文:
The problem is identifier(variable a) of array i.e. a stores the pointer of starting of array itself
you have written (&a + 1) so it consider whole array as a pointer and +1 points p to next location after size of array
eg. array has addressed 100,104,108,112,116
&a+1 -> 120
use a+1 instead of &a+1
a+1 -> 104
so the new code will be
int a[5] = { 1, 2, 3, 4, 5 };
int* p = (int*)(a + 1);
printf("%d, %d", (*a+1), *(p - 1));
this gives expected output as 2,1
hope this clears doubt
more to say int *a and int a[] are somewhat similar in pointer but not exactly.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论