这段代码中的第二个溢出在哪里

时间:2014-07-22 07:34:03

标签: c

以下是来自GNU C reference manual Pg 74的代码:

  

如果您的代码使用带符号的循环索引,请确保索引不能   溢出,以及从索引派生的所有已签名表达式。   这是一个有问题的代码示例,有两个实例   溢出。

for( i = INT_MAX - 10 ; i <= INT_MAX; i++)
    if( i+1 < 0 ) //first overflow
    {
        report_overflow();
        break; 
    }
  

由于两次溢出,编译器可能会优化掉或   以与...不兼容的方式转换两个比较   环绕式假设。

3 个答案:

答案 0 :(得分:4)

GNU C reference manual意味着你有两个可能的溢出。第一个是

中的i++语句
for( i = INT_MAX - 10 ; i <= INT_MAX; i++)

,第二个是<{p>中的i+1

if( i+1 < 0 ) //first overflow

示例C代码避免使用

的永久循环
if( i+1 < 0 ) //first overflow
{
    report_overflow();
    break; 
}

这段代码,为此,您依赖签名的环绕行为。

然而,A.3 apendix告诉您不应该依赖签名的环绕行为,因为优化器利用其未定义的行为并且可能生成与您期望的行为不同的代码。这是if( i+1 < 0 )段代码的情况,它依赖于当iINT_MAX时会发生回旋。

作为结论,上面的代码在被编译器优化后可能会失败。

答案 1 :(得分:2)

从评论转换:

i <= INT_MAX始终为true,因此循环永远不会退出。所以这是一个错误,因为i ++溢出。

因为它总是正确的,编译器可能会优化这个条件,这显然不是预期的。

答案 2 :(得分:2)

由于休息,应该没有 没有休息,这将是一个永恒的循环,并在++i上溢出 因为i <= INT_MAX对于i的所有值都为真(假设i是整数)