[英]Why GCC/Clang behaves differently on initialization in different cases?
我在GCC和Clang / LLVM中尝试了以下版本的代码:
版本1
#include <stdio.h>
main() {
work();
return 0;
}
work() {
int b;
printf("b: %d \n", b);
}
版本2
#include <stdio.h>
main() {
work();
return 0;
}
work() {
int a = 1;
int b;
printf("a: %d b: %d \n", a, b);
}
版本3
#include <stdio.h>
void work() {
int a = 1;
int b;
printf("a: %d b: %d \n", a, b);
}
int main(int argc, char** argv) {
work();
return 0;
}
对于GCC,
版本1输出b: 0
。
版本2输出a: 1 b: 4195728
。
版本3输出a: 1 b: 1742650088
。
对于Clang
(LLVM),
版本1输出b: 0
。
版本2输出a: 1 b: -1643302816
。
版本3输出a: 1 b: 0
。
我多次在几台机器上运行相同的代码。 产生“ 0”的位总是产生“ 0”,即在这种情况下, b
被初始化。
问题:
是什么使GCC和Clang在版本1中始终产生“ 0”?
是什么使Clang在版本3中始终产生“ 0”?
读取永不初始化且永不使用其地址的变量具有未定义的行为。 这意味着编译器实现者可以随意选择。 因此,如果您真的有兴趣直接询问实施者,而不是我们。 但是正如Pascal所建议的那样,我认为他们不会对您的问题很感兴趣,并且我还怀疑您是否会在他们的文档中发现任何有趣的东西。 但是,由于这些是开放源代码编译器,因此您可以查看源代码以查看它们在做什么。
本质上,您不能指望代码中有任何明智的选择。
如果您对编译器以及编译器要告诉您的东西很感兴趣,请至少为代码打开一些警告(使用-Wall
)。 根据现代标准,您拥有的前两个版本甚至都不是C。
您正在访问未初始化的变量b。 C ++标准未指定读取值时的值。 在同一编译二进制文件的不同运行中,它可能会有所不同。 这完全取决于变量“ b”在内存中的位置。 编译器不会将其初始化为任何值。
实际上,我相信这是“未定义”的行为,完全是未定义的行为,而编译器将是有效的,符合标准的C ++编译器,它将格式化硬盘或使应用程序崩溃或使OS崩溃。
简而言之:不要读取未初始化的变量,也不要期望这样做时会读取什么值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.