C11标准似乎意味着具有常量控制表达式的迭代语句不应该被优化掉。我采纳了 这个答案的建议,它特别引用了标准草案第6.8.5节:
控制表达式不是常量表达式的迭代语句... 可以由实现假定终止。
在这个答案中,它提到像 while(1) ;
这样的循环不应该进行优化。
那么... 为什么 Clang/LLVM 优化了下面的循环(用 cc -O2 -std=c11 test.c -o test
编译) ?
#include <stdio.h>
static void die() {
while(1)
;
}
int main() {
printf("begin\n");
die();
printf("unreachable\n");
}
在我的机器上,打印出 begin
,然后是 在非法指令下崩溃(ud2
陷阱放在 die()
之后)。在编译器资源管理器上(又名 Godbolt) ,我们可以看到在调用 puts
之后没有生成任何东西。
让 Clang 在 -O2
下输出一个无限循环是一个出人意料的困难任务——而我可以重复测试一个 volatile
变量,这涉及到一个我不想读取的内存。如果我这么做:
#include <stdio.h>
static void die() {
while(1)
;
}
int main() {
printf("begin\n");
volatile int x = 1;
if(x)
die();
printf("unreachable\n");
}
... Clang 打印 begin
后面跟着 unreachable
就好像无限循环不存在一样。
如何让 Clang 在打开优化的情况下输出正确的、无内存访问的无限循环?