Boj*_*V03 4 c optimization gcc integer-overflow infinite-loop
我已经编写了此C代码,用于查找等于其数字的阶乘之和的所有整数的总和。在没有任何GCC优化标志的情况下完成该工作大约需要一分钟,使用-O1可以将时间减少约15-20秒,但是当我尝试使用-O2,-O3或-Os时,它陷入了无限循环。
int main()
{
int i, j, factorials[10];
int Result=0;
for(i=0; i<10; i++)
{
factorials[i]=1;
for(j=i; j>0; j--)
{
factorials[i] *= j;
}
}
for(i=3; i>2; i++) //This is the loop the program gets stuck on
{
int Sum=0, number=i;
while(number)
{
Sum += factorials[number % 10];
number /= 10;
}
if(Sum == i)
Result += Sum;
}
printf("%d\n", Result);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我已查明这for(i=3; i>2; i++)
是问题的原因。所以很明显i
永远不会小于2?
这与整数溢出行为未定义有关吗?如果是这样,那么有关这些情况下程序究竟发生了什么的更多信息?
编辑:我想我应该提到,我知道其他编写for循环的方法,这样它就不会使用溢出(我希望INT_MAX + 1等于<2的INT_MIN),但这是只是做一个随机测试以查看会发生什么,所以我在这里张贴了它以了解到底发生了什么:)
循环是for (i = 3; i > 2; i++)
,它没有break
语句或其他退出条件。
最终i
会达到INT_MAX
然后i++
整数将导致整数溢出,从而导致不确定的行为。
可能Sum
或Result
之前也会溢出i
。
当保证某个程序会触发未定义的行为时,该程序的整个行为都是未定义的。
gcc因积极优化触发UB的路径而闻名。您可以检查汇编代码以查看实际情况。也许-O2
和更高的情况下,除去循环结束条件检查,但-O1
把它放在那里的“依赖” INT_MAX + 1
导致INT_MIN
。