指向作用域外变量的指针是否安全?

14

示例代码:

#include <stdio.h>
int main (){
    int *p;
    {
        int v = 1;
        p = &v;
    }
    printf("%d\n", *p);
    return 0;
}

这段代码可以正常运行,但我不确定是否有保证 v 的地址会被保留。

3个回答

27

没有任何保证。

一旦v超出其作用域,任何与它相关的操作(即使是通过指针进行)都被视为未定义行为

与其他未定义行为一样,仅因其在一个操作系统、编译器、编译器版本或某个特定时间运行良好,并不意味着它会在另一个上也能正常工作。


4
在这种特定情况下,您可能会注意到行为差异取决于编译器优化设置。同样的,没有什么是一成不变的,因为C标准没有定义在这里应该发生什么。 - Merlyn Morgan-Graham

8

在Merlyn的回答基础上,有一种情况可能会导致您没有预期的结果:

#include <stdio.h>
int main (){
    int *p;
    {
        int v = 1;
        p = &v;
    }
    {
        int w = 2;
        printf("%d\n", w);
    }
    printf("%d\n", *p);
    return 0;
}

编译器可以通过在堆栈上共享vw的内存空间来进行优化。但是,编译器可能不会对此进行优化 - 这就是为什么在其封闭块结束后使用指向变量的指针的行为未定义的原因。程序可能会输出"2"和"1",或者"2"和"2",或者"2"和完全不同的内容,这取决于使用的编译器和设置。

3
你最后一段话是错误的。根据C99 §6.8.5.3,“如果条件子句clause-1是一个声明,那么它声明的任何标识符的作用域是该声明的剩余部分和整个循环,包括另外两个表达式”。它不在main函数的其余作用域内。 - Matthew Flaschen
1
@Matthew:你确定它指的是生命周期而不仅仅是词法作用域吗? - cdhowie
1
我相信它是两者兼备的。脚注中写道:“因此,条款1为循环指定了初始化,可能声明一个或多个变量用于循环”(强调添加)。C++标准(§6.5.3)更清晰地解释了这一点(但我认为是等效的),展示了如何创建模拟块。 - Matthew Flaschen
2
@Matthew:我明白了。我已经从我的答案中删除了文本;我相信剩下的部分是正确的。 - cdhowie

0

是的,有时它会起作用,但人们不能确定它是否有效... 它有时不仅会导致总线错误,甚至可能导致整个程序崩溃...

我会给你一个例子

看一下这个... http://www.functionx.com/cpp/examples/returnreference.htm

在这里,他试图返回一个超出范围的变量的引用...(大错特错)...但它确实起作用...

你无法保证...所以最好(不是更好)永远不要返回超出范围的数据的引用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接