考虑以下 C 程序
#include <stdio.h>
typedef struct s {
int x;
} s_t;
int main() {
int x;
s_t a;
scanf("%d", &x);
if (x > 0) {
s_t a;
a.x = x;
}
printf("%d\n", a.x);
}
if 分支中的 a
结构变量明显隐藏了 main 中的 a
结构变量。人们会认为 printf 中的输出是未定义的,但对于 GCC,作用域变量似乎等于主变量。
例如
gcc test.c -o test
echo 10 | ./test
将输出 10。
另一方面,通过 clang 运行它,会按预期进行
clang test.c -o test
echo 10 | ./test
输出 -2145248048。
这是 GCC 错误还是触发了某种未定义的行为?
海湾合作委员会 4.8.2 clang 3.4
最佳答案
正如其他人所提到的,您正在读取一个未初始化的局部变量并且它是未定义的。所以,任何事情都是合法的。话虽如此,这种行为有一个特殊的原因:gcc
尽可能多地重用堆栈上的变量(即,只要生成的代码可证明是正确的)。您可以使用 -fstack-reuse
选项进行微调。
要禁用堆栈重用:
gcc test.c -o test -fstack-reuse=none
echo 10 | ./test
4195808 # prints some random number.
为所有变量启用堆栈重用:
gcc test.c -o test -fstack-reuse=all #, or -fstack-reuse=named_vars
echo 10 | ./test
10 # prints 10, as it reuses the space on the stack.
这在 GCC Code Generation Options 上有完整记录.
关于c - GCC 中结构变量的作用域规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30854828/