代码如下:
int a[5] = { 1, 2, 3, 4, 5 };
int* p = (int*)(&a + 1);
printf("%d, %d", (*a+1), *(p - 1));\
// output 2, 5
因为我相信 p 指向数组 a 中的第二个元素,即 2。所以 *(p-1) 的输出是 1。 但是在VS *(p-1)输出5,是什么原因呢? 感谢您的帮助!
我相信输出应该是 2, 1.
您的问题的答案在于您(可能)在插入
(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
是pointer-to-int[5]
类型,也意味着sizeof(a)
等于5*sizeof(int)
...这意味着(&a+1)
指向到数组末尾后的地址(即如果你有一个 5 整数数组的数组,下一个 5 整数数组的位置),not 到第二个 int
你的数组。
所以当你在你的代码中评估
*(p-1)
时,你正在获取一个指向 &a[5]
的指针(它不存在,但没关系)然后从中减去 1 int
,这给你一个指向 &a[4]
的指针
,您取消引用以从数组中获取值5
。
问题是数组的标识符(变量a)即a存储数组本身的起始指针
你已经写了 (&a + 1) 所以它将整个数组视为一个指针并且 +1 指向 p 到数组大小之后的下一个位置
例如。数组地址为 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[] 在指针上有些相似,但不完全相同。
以下是代码的工作原理:
int a[5] = { 1, 2, 3, 4, 5 };创建一个包含 5 个元素的整数数组 a 并使用值 1、2、3、4 和 5 对其进行初始化。
int* p = (int*)(&a + 1);创建一个整数指针 p 并将其设置为数组 a 末尾的地址。 &a 表达式返回一个指向整个数组 a 的指针,向它加 1 会使指针前进数组的大小,即 sizeof(int) * 5 个字节。然后指针被转换为 int* 类型。
(*a+1) 的计算结果为 1+1,等于 2。*a 周围的括号是不必要的,因为 a 是一个数组并且可以衰减到指向其第一个元素的指针。
*(p - 1) 访问 p 指向的地址前一个整数地址处的值。由于 p 指向的是 a 末尾刚过去的地址,因此 p-1 指向 a 的最后一个元素,即 5.
因此printf语句的输出为2, 5.
如果您有任何困惑,请告诉我。