6

我试图理解 C 中的堆栈帧,所以我编写了一个简单的 C 代码来分析堆栈帧。

  • 首先,fun1() 返回一个局部变量的地址,该变量初始化为 10 到 ptr,这会导致警告,但没关系......如果我现在打印 *ptr 的值,它会打印 10,即使这样也没关系.. .

  • 接下来 fun2() 返回一个甚至没有初始化的局部变量的地址,如果我现在尝试打印 *ptr 的值,无论我返回的是 a 还是 b 的地址,它都会打印 10 ...

  • 为了了解这里实际发生了什么,我使用了 gdb。使用 gdb,我开始逐步调试,当我到达 fun2() 中的“ return &a ”行时,我尝试打印 b 的地址,打印 &b但它打印了 Can't take address of “b” which is not一个左值。

我不明白当我尝试打印 a 的地址时,打印 &a它打印得非常好,那么为什么不打印 b 的地址。* 为什么当 a 是左值时 b 不是左值?

# include <stdio.h>

int * fun1() {
    int a = 10; 
    return &a; 
}

int * fun2()
{
    int a;
    int b;
    return &a;           // return &b;
}

int main ()  
{
    int *ptr;
    ptr = fun1();
    ptr = fun2();
    printf ("*ptr = %d, fun2() called...\n", *ptr);
    return 0;
}
4

2 回答 2

3

编译器正在优化fun2.

如果你返回&a,那就是优化掉了int b;。如果你返回&b,那就是优化掉了int a;。如果您添加一些虚拟计算,您会看到返回值的地址会有所不同。

int * fun2()
{
    int a;
    int b;
    int* p = &a;
    p = &b;
    return p;
}

更改以打印和main的返回值。fun1fun2

int main ()  
{
    int *ptr;
    ptr = fun1();
    printf ("ptr = %p, fun1() called...\n", ptr);
    ptr = fun2();
    printf ("ptr = %p, fun2() called...\n", ptr);
    printf ("*ptr = %d, fun2() called...\n", *ptr);
    return 0;
}

当我运行此代码时,我得到以下示例输出:

ptr = 0x7ffff98c70ec, fun1() 调用...
ptr = 0x7ffff98c70e4, fun2() 调用...
*ptr = 32749, fun2() 调用...
于 2014-04-25T05:40:39.407 回答
0

将地址返回给 b 时,它对我来说编译得很好。但是您不应该返回局部变量的地址。 看看这个链接

于 2014-04-25T05:36:01.913 回答