Brainteaser:指针参考值

时间:2012-03-09 20:22:52

标签: c pointers reference

  

可能重复:
  Can a local variable's memory be accessed outside its scope?

今天我参加了一个关于基本C编码的研讨会,我们偶然发现了一个脑力激荡器,现在的助手都没有能够回答我的内容。

代码是:

#include <studio.h>

int *f(int a) {
    int b = 2 * a;
    return &b;
}


int main(void) {
    int *p4;
    int *p8;
    p4 = f(4);
    p8 = f(8);
    printf("p4: %i / p8: %i\n", *p4, *p8);
}

我知道代码有什么问题,我自己也不会编写类似的东西,但它仍然很有趣。

输出是:

p4:16 / p8:16

当然是

p4:8 / p8:16

我最初的预期是我们会收到一个错误,因为在通过&b的功能f之后不再存在(变量范围)。

助理们把它解释为“幸运的一拳”,那个位置的记忆中还有一些东西,但那并没有真的为我做。

我认为id在这里发布,看看是否有人有更好的解释。

IMPORTANT:这不是一个如何在函数中添加2个int的问题 - 我完全有能力 - 它:为什么在为printf检索它时将数字16存储在* p4。

期待鼓舞人心的答案, 塞巴斯蒂安

2 个答案:

答案 0 :(得分:5)

  

为检索printf时,为什么数字16存储在* p4。

未定义的行为 - 任何事情都可能发生。

int *f(int a) {
    int b = 2 * a;
    return &b;
}

您正在返回一个指向已销毁变量的指针,然后您将访问该内存位置。那就是UB。

答案 1 :(得分:2)

此行包含多个未定义行为案例:

*p4 = *(f(4));

第一个问题是在右侧,正如您所指出的那样f返回一个指向自动变量的指针。使用该指针是一个错误,正如您所知,在这种情况下和测试中,未定义的行为不会显示为崩溃,而是访问内存(即堆栈中的某个位置)。

第二个问题是左手边。指针p4从未初始化,这意味着您还在表达式*p4中导致未定义的行为,由于某种原因导致应用程序崩溃。但不知道p4的价值是什么,没有进一步的分析是可能的。即它可以指向内存中的任何位置,无论是否有效,并且后面的任何操作都可能正在更改该地址的值,因此您不能指望任何位置。

修改后

p4 = f(4);
p8 = f(8);

这仍然是未定义的行为,但对行为的简单解释(即使它是常见的,你不能依赖)是变量b在两次调用中都位于内存中的同一地址f。这可以通过打印指针(而不是指向的值)轻松测试。对于如何/为何发生这种情况的解释是第一个f调用的堆栈帧被重用于第二个,并且因为函数完全相同,所有内部变量的位置是相同的 for连续2次通话