添加一行代码会更改变量的内存地址

时间:2015-09-02 22:54:16

标签: c pointers memory

原始代码是:

int main(){
int sam= 19;
int *pSam= &sam;
printf("Address \t name \t value\n");
printf("%p \t %s \t %d\n", pSam, "sam", sam);

return 0;

sam的内存地址显示为= 0028FF18。

但是,如果我对变量一无所知,只需在'return 0;'上方添加另一行代码。这是:

 printf("%p \t %s \t %p", &pSam, "sam", pSam);

然后运行程序,sam的内存地址变为0028FF1C,即使我刚刚打印出一些基本内容。

为什么?

2 个答案:

答案 0 :(得分:0)

正如评论中所提到的,这几乎肯定是关于优化的。

此:

int main() {
   int sam = 19;
   int *pSam = &sam;
   printf("Address \t name \t value\n");
   printf("%p \t %s \t %d\n", pSam, "sam", sam);

   return 0;
}

基本上等同于:

int main() {
   int sam = 19;
   /* int *pSam = &sam; */
   printf("Address \t name \t value\n");
   /* printf("%p \t %s \t %d\n", pSam, "sam", sam); */
   printf("%p \t %s \t %d\n", &sam, "sam", sam);

   return 0;
}

换句话说,它可以在没有变量pSam的情况下完成,因此,智能编译器将优化该变量。根据处理器的不同,即使没有对其进行优化,它也可以将所有内容存储在寄存器中,而不是在堆栈上分配存储空间。

但是,如果你想取pSam地址,那么很明显它不能被优化掉或放入寄存器中,因为如果你做其中任何一项,那么它&# 39;不会有地址。因此,当你这样做时,你强制编译器为它分配内存,几乎可以肯定是在堆栈上。并且,在这种情况下,看起来当你这样做时sam的地址 - 也必须在堆栈上分配,因为你也取其地址并输出它 - 结果正在改变,可能是因为你的编译器在pSam之前在堆栈上分配sam

答案 1 :(得分:0)

虽然不是那么明显,可能导致这是一个无效的编译器优化。

在原始代码中

int main() {
    int sam = 19;
    int *pSam= &sam;

    printf("Address \t name \t value\n");
    printf("%p \t %s \t %d\n", pSam, "sam", sam);

    return 0;
}

您可能会注意到pSam变量的地址从不需要,因此编译器可以完美地优化该变量,从而导致更小(几个字节......)堆叠。

现在,当您在混音中添加另一行时。

printf("%p \t %s \t %p", &pSam, "sam", pSam);

编译器优化失效,也就是说,它的断言(永远不会使用pSam的地址)不再有效,因此优化不可用。这意味着变量pSam现在没有被优化掉,现在实际上存在于堆栈空间中,从而推动,移动或以其他方式修改过程中其他堆栈变量的地址。