我有一个关于 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/