程序将生成阶乘数,直到它发生溢出。表达式r * j <= UINT_MAX
用于检测溢出。现在,如果我将表达式重写为此for (unsigned i = 0;;++i) {
unsigned r = 1;
for (unsigned j = 2; j <= i; ++j) {
if (r <= UINT_MAX / j)
r *= j;
else {
printf("Overflow!\n");
}
}
}
,它将进入无限循环。我的问题不是如何检测整数溢出。这就是为什么表达式会让进程进入无限循环。
{{1}}
答案 0 :(得分:3)
无符号整数类型的算术 modulo 其最大值加1.
在您的情况下,我们有算术模(UINT_MAX+1)
。
因此,操作r*j
始终给出结果<= UINT_MAX
,并且比较始终为真。
但是,当r
与UINT_MAX / j
进行比较时,真实(数学)算术与无符号类型算术一致,因为UINT_MAX / j
在数学上与范围unsigned
。
这解释了为什么在C代码中条件的真或假与数学比较完全相同。
因此,r <= UINT_MAX/j
方法是正确的。