我写了这段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;
}
我已经确定for(i=3; i>2; i++)
是问题的根源。那么显然,i
永远不会小于2?
这是否与整数溢出行为未定义有关?如果是,那么在这些情况下程序到底发生了什么?
编辑:我想我应该提到,我知道编写这个for循环的其他方式,以避免使用溢出操作(我希望INT_MAX+1等于INT_MIN,即<2),但这只是一个随机测试,我在这里发布它是为了找出到底发生了什么 :)
-funsafe-loop-optimizations
尝试godbolt示例可以很好地说明这一点,我们可以看到gcc将其转换为一个什么也不做的无限循环。还可以参见这个和这个。 - Shafik Yaghmouri
达到最大正值时,它会变成小于 2,然后(使用二进制补码表示)它就成为了一个负数所能表示的最大绝对值! - Sir Jo Black