簡體   English   中英

C:表達式求值中的隱式轉換和整數溢出

[英]C: Implicit casting and integer overflowing in the evaluation of expressions

我們來看看代碼

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

如果我們添加a和b的值並且總和超過int的最大值,那么比較的完整性是否會受到影響? 我當時認為可能存在隱式向上轉換或溢出位檢查,這將被考慮到此表達式的評估中。

C不會做這樣的事情。 它將無聲地溢出並導致可能不正確的比較。 您可以自己升級,但不會自動完成。

測試證實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文檔...

啊,是的,並且上傳不會自動發生......

請參閱K&R書中的第2.7節“ 類型轉換

如果向上轉換沒有獲得任何位(在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生成的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM