问题描述
我一直在尝试理解指针,特别是指针[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 个字节,并认为我可以通过 z[1] 或 *(z+1) 返回存储在 x 地址的值,这很好用。
然而,当我删除前 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.
我的想法是,在 Linux 上的 gcc 10.2.0
上,
- 在第一种情况下,当使用
&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