在C++中循环为
for(;;) {}
是UB,而不是C?
据表示,在https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2809r0.html人中,有good reasons人这样做.有什么简单的例子可以清楚地说明这一点吗?
在C++中循环为
for(;;) {}
是UB,而不是C?
据表示,在https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2809r0.html人中,有good reasons人这样做.有什么简单的例子可以清楚地说明这一点吗?
原因仅仅是优化.
如果编译器可以假定所有循环都终止而没有副作用,则不必证明这一点.
如果允许非终止循环,编译器只有在证明其可终止性的情况下才被允许执行某些优化,这在一般情况下是不可能的,因此它将变成模式识别游戏.有什么好处呢?
The underlying issue is that non-termination is a kind of side-effect on itself.当且仅当环路终止时,才能观察到在环路终止后肯定会发生的任何可观察到的效果,即使环路没有任何影响.
当然,对于if(expr) return;
也可以进行完全相同的推理,编译器不允许将if
后面的东西移到if
之前,除非它能证明expr
是假的.但是if
是基本的控制流机制,而非终止循环不是(IMHO).
请使用以下代码.
int collatz_conjecture(int i){
while(i!=1){
if ((i%2)==0)
i/=2;
else
i=i*3+1;
}
return i;
}
int main(){
collatz_conjecture(10);
return 5;
}
对于臭氧,GCC将其汇编为:
collatz_conjecture(int):
mov eax, 1
ret
main:
mov eax, 5
ret
那么,编译器是否证明了Collatz猜想,以确定它应该为所有数字返回1
?当然不是,这只是终止假设允许的优化之一(以及UB可能发生的地方).循环可以终止的唯一方法是IF i==1
,因此它可以在循环之后假定为i==1
,并使用它进行进一步的优化->;函数总是返回1,因此可以简化为它.
更有用的例子可以是交错复制.如果你有
loop A
loop B
允许编译器在不知道A
终止的情况下对它们进行交织.许多矢量化操作都依赖于这一假设.
同样,在循环假定循环将终止之前,对一些独立的循环后操作进行重新排序.
编辑:我指的是科拉茨猜想,不是戈德巴赫……