C Windows中奇怪的指针行为

C Windows中奇怪的指针行为,c,pointers,memory-address,C,Pointers,Memory Address,我一直在试图理解指针,特别是指针[I]符号,它相当于*(指针+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("addres

我一直在试图理解指针,特别是指针[I]符号,它相当于*(指针+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));

}
#包括
内部主(空){
int x=10;
int y=20;
int*z=&y;
printf(“x的地址:%u”,&x);
printf(“y的地址:%u”,&y);
printf(“地址处的值:%u\n”,*(z+1));
}
我注意到“y”在“x”之前存储了4个字节,并认为我可以通过z[1]或*(z+1)返回存储在x地址的值,这很好

然而,当我删除前两个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));

}
#包括
内部主(空){
int x=10;
int y=20;
int*z=&y;
printf(“地址处的值:%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;
}
但是,如果我使用
&x
注释掉该行

//printf(“地址差异:&x-&y=%d.\n”、&x-&y);
输出将是一致的,如下所示

*(intp + 1) is 10.
*(intp)     is 20.
*(intp - 1) is 0.
我的想法是,在我的
GCC10.2.0
Linux上

  • 在第一种情况下,当使用
    &x
    时,使用
    x
    存储在比
    y
    低4字节的地址。作为
    int
    在我的计算机上有4个字节,
    &x-&y
    始终是
    -1
  • 在第二种情况下,当未使用
    &x
    时,
    x
    存储在比
    y
    高4字节的地址
因此,编译器确实设置了空间来存储
x
y
,即使未使用
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

您是否尝试过使用调试器对这两种情况执行堆栈跟踪?您确定第二个示例中打印的值不仅仅是某个垃圾值吗?它可能是,但我仍然不知道为什么删除这两个打印会导致这种情况。为什么编译器会浪费内存并保留
x
,而这在您的程序中从未使用过?该变量很可能根本不存在于可执行文件中。您还可以通过在
printf
中使用未验证的格式说明符调用未定义的行为,并访问超出范围的内存。要打印指针,必须使用
%p
而不是
%u
*intp
是一个
int
,使用
%u
打印它将调用UB。而
&x-&y
是一个
ptrdiff\u t
,您也可以通过使用
%d
而不是
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