整數算術溢出問題的分析

    這篇對整數的一些基本運算產生的溢出問題進行分析。函數

  當你進行加減乘除運算的時候,若是這個數字很大,運算產生的結果就可能會出乎你最初設計程序的預料,這對程序來講是一種很可怕的漏洞,這讓一些惡意的訪問者對程序做出一些破壞性的事情,這樣形成的危害多是很大的。spa

這裏先定義一些宏定義做爲返還值:設計

 

#define OVERFLOW 1      //算術溢出(正溢出)
#define NOT_OVERFLOW 0             //未溢出
#define NEGATIVE_OVERFLOW -1      //負溢出

 

當進行無符號整數加法計算的時候。code

  無符號整數的範圍是 0 ≤ x  UMax ,UMax = 2w - 1 (w是當前類型的位數) ,若是兩個數相加的結果小於任何一個數,那麼就能夠判斷算術溢出。判斷的代碼以下:
blog

 

int uadd_ok(unsigned x, unsigned y)
{
    unsigned uadd=x+y;
    if( uadd < x || uadd < y)
        return OVERFLOW;
        
    return NOT_OVERFLOW;
}

 

當進行有符號整數加法計算的時候。get

  有符號整數的範圍是 TMin ≤ x ≤ TMax TMin = -2w-1 ,TMax = 2w-1 - 1 那麼爲什TMax的絕對之爲何會比TMin的絕對之小一,那麼假設 w= 4 觀察一下。由於有符號數的最高位是符號位,因此TMax的最高位就是 0 ,爲了讓數字更大那麼其他就應該是 1 ,那麼 TMax (4) = 0111 = 22+21+20=23-1=2w-1-1。有符號數的負數部分通常都是用補碼錶示的 TMin 最高位就須要是 1 由於只有最高位是表明負數,其他位都是正數,最後這個數的值是各個位的值的加和獲得的,因此其他位都須要是 0 ,那麼 TMin(4)=1000= -23 = -2w-1 。那麼判斷有符號數加法的代碼一種錯誤以下,它利用了阿貝爾羣得知補碼加法的時候,(x+y)-y=y 在溢出的狀況下是成立的。因此就有可能出現以下的代碼:
it

 

int tadd_ok(int x, int y)
{
     int sum=x+y;
     return (sum - y == y) && (sum - x == y) ; 
}    

 

可是這個代碼的返回值永遠是 1, 由於在不溢出的狀況下表達式成立是顯而易見的。class

因此就須要考慮多方面的因素了,兩個數都大於零的時候,若是結果是負數那麼可判斷溢出。若是兩個數都是負數,結果爲正數那麼判斷也溢出。程序

代碼以下:di

 

int tadd_ok(int x, int y)
{
    int tadd=x+y;
    if( x > 0 && y > 0 )
        if( tadd < 0 )
            return OVERFLOW;
    
    if( x < 0 && y < 0 )
        if( tadd >= 0 )
            return NEGATIVE_OVERFLOW;
    
    return NOT_OVERFLOW;
}

 

當進行有符號減法運算的時候。

  這個時候你可能想像這樣調用寫好的 tadd_ok( x, -y );  函數,可是實際上在一些狀況下這是錯誤的,由於 TMin = -TMin ,這樣你想要的 -TMin 就沒有變成 | TMin | 卻變成了TMin 因此就須要增長一些判斷。

代碼以下:

 

int tsub_ok(int x, int y)
{
    if( y != 0 && y == -y )
    {
        if( x >= 0 )
            return OVERFLOW;
        return NOT_OVERFLOW;
    }
    return tadd_ok(x,-y);
}

 

 

當是乘法運算的時候不論有符號仍是無符號,溢出的部分都是直接截掉的。

  固然乘法是可使用 ( x * y ) / x = y 進行判斷的由於溢出的時候這是不成立的,固然你須要保證 x , y 不是零 ,若是是零做爲除數是不合理的。

因此能夠寫出以下代碼:

 

int tmult_ok(int x, int y)
{
    int tmult=x*y;
    if( x != 0 && y!= 0 )
    {
        if( tmult / x == y )
            return NOT_OVERFLOW;
        return OVERFLOW;
    }
    return NOT_OVERFLOW;
}
相關文章
相關標籤/搜索