Windows 中的奇怪指针行为

Weird pointer behaviour in Windows

我一直在尝试理解指针,特别是指针[i] 表示法,它等同于 *(pointer + i),即解引用下一个地址的值,所以如果它是一个 int 指针下一个 4 字节地址。我尝试了 运行 下面的代码:

#include <stdio.h>

int main(void){
  int x = 10;
  int y = 20;

  int* z = &y;
  printf("address of x: %u ", &x);
  printf("address of y: %u", &y); 
  printf("value at address: %u \n", *(z+1));

}

我注意到 'y' 在 'x' 之前存储了 4 个字节,并认为我可以 return 通过 z[1] 或 * 存储在 x 地址的值(z+1),效果很好。

然而,当我删除前 2 个 printf 时,我最终输出的是地址而不是实际值 (10),这是这种情况的代码:

#include <stdio.h>

int main(void){
  int x = 10;
  int y = 20;

  int* z = &y;
  printf("value at address: %u \n", *(z+1));

}

我假设 *(z+1) 不再指代与变量 'x' 相同的内存区域,但我很困惑为什么代码中的这种变化会导致这种情况。

一开始我以为是一次性的,所以我试了很多次,每次都得到相同的结果。

更令人困惑的是代码在 ubuntu 和 macOS 上如何按预期工作,但在 windows.

上却没有

任何有关此的帮助都将非常有用,谢谢。

这里我只能回答你的部分问题,并提出我的看法 观察。

这里是修改后的代码。

#include <stdio.h>

int main(void) {
  int x = 10;
  int y = 20;
  int *intp = &y;

  //  printf("address of x is %p.\n", &x);
  //  printf("address of y is %p.\n", &y);
  printf("*(intp + 1) is %u.\n", *(intp + 1));
  printf("*(intp)     is %u.\n", *(intp));
  printf("*(intp - 1) is %u.\n", *(intp - 1));
  printf("difference of addresses: &x - &y = %d.\n", &x - &y);

  return 0;
}

我得到了 *(intp) 一致的结果, *(intp - 1)&x - &y,而 *(intp + 1) 会改变。其中一个输出是

*(intp + 1) is 2028820428.
*(intp)     is 20.
*(intp - 1) is 10.
difference of addresses: &x - &y = -1.

但是,如果我使用 &x

注释掉该行
//  printf("difference of addresses: &x - &y = %d.\n", &x - &y);

输出会一致,如下

*(intp + 1) is 10.
*(intp)     is 20.
*(intp - 1) is 0.

我的想法是,在我的 gcc 10.2.0 上 Linux,

  • 第一种情况,当使用&x时,x是 存储在比 y 低 4 个字节的地址。作为 int 在我的电脑上是 4 个字节,&x - &y 总是 -1.
  • 第二种情况,不用&x时,x 存储在比 y 高 4 个字节的地址。

所以编译器确实设置了 space 来存储 xy,即使未使用 x。但是我 不知道为什么他们的立场在这两种情况下会有所不同。编译器 可以尝试优化代码,但我对此知之甚少

此外,如果您想尝试使用 gdb 来测试 地址,你可以试试

gcc -g thecode.c
gdb a.out
(gdb) break main
(gdb) run
(gdb) p &x
(gdb) p &y
(gdb) p &x + 1
(gdb) step
(gdb) (press enter directly to use the last same command...)
(gdb) quit