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

时间:2020-03-05 18:49:36  来源:igfitidea点击:

让我们看一下代码

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

如果我们将a和b的值相加,并且总和超过int的最大值,比较的完整性是否会受到损害?我当时在想可能会有一个隐式的强制转换或者溢出位检查,这将在对该表达式的求值中考虑。

解决方案

回答

C不会做这种事情。它会静默溢出,并可能导致不正确的比较。我们可以自己上演,但不会自动完成。

回答

我相信这可能是特定于平台的。查看有关如何处理溢出的C文档...

啊,是的,并且不会自动发生up ...

回答

请参阅《 K&R》一书中的2.7节,类型转换

回答

测试确认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

回答

如果向上转换没有获得任何收益(无法保证C中的sizeof(long)> sizeof(int)),则可以使用以下条件进行比较,并确定如果可以使用,则向上溢出的检查几乎肯定会更快, 尽管。

#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生成的代码。