溢出

溢出

就是結果值超出了被賦值對象的類型長度。


例如 8 位(1字節)的 char 。根據它有符號還是無符號, 它可以包含最大數127 或 255 。
下面的乘法向一個 char 賦值 256 ,因而導致了溢出:


int main() 
{
    char value = 32;
    int ival = 8;

    value = ival * value;
    //cout << "value: " <<value << endl;
    cout << "value: " << static_cast<int>(value) << endl;
}

表示256需要9位,因而向value賦值256導致了與其相廣聯的內存的溢出。value包含的實際值是未定義的,所以在執行時就可能會引起問題。
當用表達式:

        cout << "value: " << value << endl;

試圖輸出它時,程序輸出結果如下:
這裏寫圖片描述
想了一會後,意識到,在ASCIL碼集中,0代表空(NULL)字符,所以什麼也不會輸出。如下特殊表達式:

cout << "value: " << static_cast<int>(value) << endl;

這種情況下,我們吧value轉換位一個int類型的對象。這時候程序輸出:
這裏寫圖片描述

在本例中,我們改變的不是value相關的值,而是它被輸出操作符解釋的方式。當它被當作char型時,值會被映射到相關聯的ASCIL表上,輸出對應的字符;當被當作int時,會直接輸出它的值。


這裏順便補充一下,C++支持的四種類型強制轉換:

  1. const_cast:去掉對象的const屬性的
  2. static:編譯器認爲可以支持的強轉方式,安全性略高
  3. reinterpret_const:類似於C的強轉
  4. dynamic_cast:PTTI強制類型轉換(run-time type information)

最近經別人介紹看到了《C標準》(The Standard C Library)這本書,(網上很多需要付費下載,找了好久資源的)
在這本書的limits那章提到了與內置類型表示有關的信息,例如一個類型能表示的最大值和最小值,以及怎樣使用這些頭文件防止溢出(overflow)和下溢(underflow)。

1.在下面給出的值會被適合在#if預處理指令中使用的常量表達式代替。

這裏寫圖片描述

例如,假設在要表示某個值在VAL_MIN和VAL_MAX之間的有符號數據,就可以通過以下代碼來防止程序出現翻譯錯誤:

#include <assert.h>
#include <limits.h>
#if VAL_MIN < INT_MIN || INT_MAX < VAL_MAX
#error values out of range
#endif

使用

#include <assert.h>
#include <limits.h>
#if VAL_MIN < INT_MIN || INT_MAX < VAL_MAX
    typedef long Val_t;
#else
    typedef int Val_t;
#endif

然後就可以把所有在這個範圍中變化的數據對象聲明爲Val_t類型。程序就會選擇效率更高的類型。
這裏呢,

/*HANDLE OVERFLOW*/
    if(x < log(DBL_MAX))
        y = exp(x);
    else
        ...

這裏寫圖片描述

可以通過使用一個相關的宏來避免計算log(DBL_MAX),就像:

/*HANDLE OVERFLOW*/
    if (x <= PLT_MAX_10_EXP)
        y = pow(10, x);
    else
        ...      

(2)下溢
爲了避免下溢,一定要保證所有的值都大於DEL_MIN的數值。下溢的結果不像上溢那樣損失慘重,但是仍然麻煩很大。IEEE 754浮點算術提供了漸進下溢,減輕了下溢的一些最壞影響。很多浮點的實現都用零值代替一個過小而不能表示的值。這會在除以一個會產生下溢的值是,遇到麻煩。
可以作如下相應的測試:

/*HANDLE UNDERFLOW*/
if(log(DBL_MIN) <= x)
    y = exp(x);
else
    ...

if(FLT_MIN10_EXP <= x)
    y = pow(10, x);
else
    ...

if(FLT_MIN_EXP < n)
    y = ldexp(1.0, n);
else
    ...

(3)有效值丟失
當對兩個幾乎相等的值相減是就會發生有效值丟失。
一個可以阻止有效值丟失的方法——把一個很小的書和一個很大的數相加。
在加的過程中,較小的數的重要作用就可能體現不出來。

參考資料:
《C++ Primer 3rd Edition》
《C++標準》

發佈了40 篇原創文章 · 獲贊 6 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章