代码之家  ›  专栏  ›  技术社区  ›  lillq

C:表达式计算中的隐式强制转换和整数溢出

c
  •  2
  • lillq  · 技术社区  · 16 年前

    让我们记下密码

    int a, b, c;
    ...
    if ((a + b) > C)
    

    如果我们加上a和b的值,并且总和超过了int的最大值,那么比较的完整性会受到影响吗?我在想,可能有一个隐式的向上强制转换或溢出位检查,这将被分解到这个表达式的计算中。

    5 回复  |  直到 7 年前
        1
  •  7
  •   hazzen    16 年前

    C不会做这种事。它将无声地溢出并导致可能不正确的比较。你可以自己铸造,但它不会自动完成。

        2
  •  2
  •   Rob Pilkington    16 年前

    测试证实,GCC 4.2.3将简单地与溢出结果进行比较:

    #include <stdio.h>
    
    int main()
    {
        int a, b, c;
    
        a = 2000000000;
        b = 2000000000;
        c = 2100000000;
    
        printf("%d + %d = %d\n", a, b, a+b);
        if ((a + b) > c)
        {
            printf("%d + %d > %d\n", a, b, c);
        }
        else
        {
            printf("%d + %d < %d\n", a, b, c);
        }
        return 0;
    }
    

    显示以下内容:

    2000000000 + 2000000000 = -294967296
    2000000000 + 2000000000 < 2100000000
    
        3
  •  0
  •   Daren Thomas    16 年前

    我相信这可能是平台特定的。检查C文档,了解如何处理溢出…

    啊,是的,上抛不会自动发生…

        4
  •  0
  •   cwick    16 年前

    见第2.7节, 类型转换 在K&R手册中

        5
  •  0
  •   Chris    15 年前

    如果上溯没有获得任何比特(不能保证C中的sizeof(long)>sizeof(in t),那么可以使用下面的条件进行比较,并检查上溯溢出的速度,如果可以使用的话。

    #if !defined(__GNUC__) || __GNUC__<2 || (__GNUC__==2 && __GNUC_MINOR__<96)
    #   define unlikely(x) (x)
    #else
    #   define unlikely(x)     (__extension__ (__builtin_expect(!!(x), 0)))
    #endif
    
    /* ----------
     * Signed comparison (signed char, short, int, long, long long)
     * Checks for overflow off the top end of the range, in which case a+b must
     * be >c.  If it overflows off the bottom, a+b < everything in the range. */
    if(a+b>c || unlikely(a>=0 && b>=0 && unlikely(a+b<0)))
        ...
    
    /* ----------
     * Unsigned comparison (unsigned char, unsigned short, unsigned, etc.)
     * Checks to see if the sum wrapped around, since the sum of any two natural
     * numbers must be >= both numbers. */
    if(a+b>c || unlikely(a+b<a))
        ...
    
    /* ----------
     * To generate code for the above only when necessary: */
    if(sizeof(long)>sizeof(int) ? ((long)a+b>c)
           : (a+b>c || unlikely(a>=0 && b>=0 && unlikely(a+b<0)))
        ...
    

    非常适合宏或内联函数。如果你愿意的话,你可以去掉“不太可能”的,但是它们可以帮助收缩并加速gcc生成的代码。