直接使用运算符的地址与使用指针变量

时间:2019-09-11 06:15:43

标签: c pointers memory-address

我知道一个事实,即永远不要从函数返回局部变量的地址。但是,在证明事实的同时,我遇到了一个问题。考虑以下程序:

int *test()
{
    int x = 12;
    int *p = &x;
    return p;
}

int main()
{
    int *p = test();
    printf("%p",p);
    return 0;
}

它按预期打印类似0061fed0的地址。但是,如果我直接使用&返回x的地址,即test函数的更改如下:

int *test()
{
    int x = 12;
    return &x;
}

然后输出将变为00000000。那么,您能解释一下这里发生了什么吗?我正在使用Windows 10中的Code :: Blocks 17.12 IDE捆绑提供的gcc编译器。

关于重复的问题: 建议重复的问题: C - GCC generates wrong instructions when returning local stack address 说明了直接使用运算符的地址的行为,但没有解决使用指针变量返回局部变量的地址的情况,这在StoryTeller的答案中进行了解释:“当指针变大时,指针的值变得不确定它所指向(或刚刚过去)的对象达到其生命周期的尽头。”

1 个答案:

答案 0 :(得分:4)

严格来说,从C语言规范的角度来看,这是一个有效的结果。

  

6.2.4对象的存储期限(强调我的意思)

     

2对象的生存期是程序执行的一部分   在此期间,保证为其保留存储空间。一个东西   存在,具有恒定的地址,并保留其最后存储的值   整个生命周期如果在对象之外引用对象   寿命,行为是不确定的。 指针的值变为   不确定它所指向的对象(或刚刚过去的对象)何时到达   寿命结束。

因此,无论哪种情况,函数返回的值都是不确定的。您无法预测它将是什么,甚至无法以有意义的方式使用它。使用不确定值的程序具有不确定的行为,任何事情都可能发生。

因此,当您直接返回本地地址时,编译器将返回null。根据C语言本身,这是一个有效值,因为无论如何该对象很快就会死亡。但是,这样做的好处是,在现代的托管实现中,您可能会在早期使程序崩溃,并允许您修复错误。