【问题标题】:Adding a line of code changes the memory address of a variable添加一行代码会改变一个变量的内存地址
【发布时间】:2015-09-02 22:54:15
【问题描述】:

原代码是:

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。

但是,如果我对变量没有任何更改,只需在“返回 0;”上方添加另一行代码也就是:

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

然后运行程序,sam的内存地址变成了0028FF1C,虽然我只是打印了一些基本的东西。

这是为什么呢?

【问题讨论】:

  • 第一个例子中sam的地址如果不打印是怎么知道的,因为你只在第二个例子中添加了printf("%p \t %s \t %p", &pSam, "sam", pSam)?
  • 可能是在第一种情况下,编译器优化了int *pSam= &sam;,因此堆栈上的变量少了一个。
  • @ouah 我包含了 pSam,它基本上打印出内存地址 sam。
  • @mustaccio 当你说优化你的意思时?地址比原来大了 4 个字节:(从 0028FF18 到 0028FF1C )堆栈寻址增长从小到大。
  • 您确实需要将传递给printf 的指针转换为(void *) -> 检查标准(关于“指针应为void * 类型”我>

标签: c pointers memory


【解决方案1】:

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

这个:

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 的地址,那么显然它不能被优化掉或放入寄存器中,因为如果你做这些事情中的任何一个,那么它不会有地址。因此,当您这样做时,您会强制编译器为其分配内存,几乎可以肯定是在堆栈上,这里。而且,在这种情况下,看起来sam 的地址 - 也必须在堆栈上分配,因为你也获取它的地址并输出它 - 结果正在改变,可能是因为你的编译器正在分配pSam 在sam 之前的堆栈上。

【讨论】:

  • 为什么投反对票?我认为你的回答比我的更有表现力:)。
【解决方案2】:

虽然不是很明显,但可能导致编译器优化失效。

在您的原始代码中

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 现在没有被优化掉,并且现在实际上存在于堆栈空间中,因此在进程中推送、移位或以其他方式修改其他堆栈变量的地址。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    • 2019-07-14
    • 2018-04-21
    • 1970-01-01
    • 2010-10-09
    相关资源
    最近更新 更多