c - 设置指向在 C 中的局部范围内声明的变量的指针

标签 c language-lawyer undefined-behavior lifetime

我有一个关于 C 中的作用域规则的问题,最好用以下代码来说明:

#include <stdio.h>

int main(void)
{
    int * x = NULL;

    {
        int y = 42;
        x = &y;
        printf("%d\n", *x);
    }

    printf("%d\n", *x);
    *x = 74;
    printf("%d\n", *x);

    return 0;
}

运行这段代码打印出来

42
42
74

我使用带有所有警告和 -fsanitize=undefined 的 clang 编译它。

变量 y 在局部范围内声明,在右大括号后不可访问。尽管如此,我们可以使先前声明的指针引用该局部变量,并且即使在其作用域结束后我们也可以引用该内存的内容。

虽然由于程序堆栈在我的机器上的工作方式的特殊性,这段代码可能会起作用,但在我看来,此时取消引用 x 应该是未定义的行为。我对如何用 C++ 回答这个问题有了更好的感觉。如果我们使用一些带有非平凡析构函数的类,而不是像 int 这样的基本类型,那么它的析构函数将在右大括号处被调用。

此代码是否会调用未定义的行为?我不太了解 C 标准,因此对相关规则的引用将不胜感激。

最佳答案

是的,这是未定义的行为。来自 §6.2.4 2 C11 标准:

If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

变量 y 在发布的代码中具有自动存储持续时间。来自 §6.2.4 5 :

An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration....

下一段指出:

For such an object that does not have a variable length array type, its lifetime extends from entry into the block with which it is associated until execution of that block ends in any way.

因此 y 的生命周期在封闭 block 执行完成后结束,此时指针 x 的值变得不确定,尝试进行未定义行为通过 x 或任何其他方式进一步访问 y

关于c - 设置指向在 C 中的局部范围内声明的变量的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44490073/

相关文章:

C MSB 到 LSB 解释

c++ - 为什么 CRTP 中的沮丧定义行为

c - 获取超出范围的数组元素的地址是未定义的行为吗?

c++ - init-declarators 的完整表达式的定义

所有位 0 都可以是整数的陷阱表示吗?

c - 这是 C 中的未定义行为吗?如果不能逻辑地预测输出

c++ - 由 C++ 编译器优化时,F2C 翻译的代码会中断

c - 如何防止非数字或非字符输入或符号并在 C 中获得所需的输出

c++ - 在 C/C++ 中,2 double 的乘积/商精确到多少位小数

c++ - 什么时候在空实例上调用成员函数会导致未定义的行为?