数组指针引用和解引用时出现意外行为

huangapple go评论62阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年3月12日 13:51:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75711275.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定