2011-06-01 67 views
3

編譯器將源代碼作爲字符串處理,所以在C++中,例如當它鼓勵類似於unsigned char x = 150;的語句時,它從類型限制知道unsigned char必須在0255之間的範圍內。編譯時編譯器如何檢測數字溢出?

我的問題是,雖然數字150仍然是字符串什麼算法編譯器用來比較數字序列 - 150在這種情況下 - 反對類型限制?

我做了一個簡單的算法來做到這一點爲十進制,八進制,十六進制和little endian二進制類型「詮釋」,但我不認爲編譯器做這種事一樣,檢測數字溢出。

我提出的算法進行編碼,C++:

typedef signed char int8; 
typedef signed int int32; 

#define DEC 0 
#define HEX 1 
#define OCT 2 
#define BIN 3 

bool isOverflow(const char* value, int32 base) 
{ 
    // left-most digit for maximum and minimum number 
    static const char* max_numbers[4][2] = 
    { 
     //     INT_MAX       INT_MIN 
     {      "2147483647",      "2147483648" }, // decimal 
     {       "7fffffff",       "80000000" }, // hexadecimal 
     {      "17777777777",      "20000000000" }, // octal 
     { "01111111111111111111111111111111", "10000000000000000000000000000000" } // binary 
    }; 

    // size of strings in max_numbers array 
    static const int32 number_sizes[] = { 10, 8, 11, 32 }; 

    // input string size 
    int32 str_len = strlen(value); 

    // is sign mark exist in input string 
    int32 signExist = ((base == DEC || base == OCT) && *value == '-'); 

    // first non zero digit in input number 
    int32 non_zero_index = signExist; 

    // locate first non zero index 
    while(non_zero_index < str_len && value[non_zero_index] == 0) non_zero_index++; 

    // if non_zero_index equal length then all digits are zero 
    if (non_zero_index == str_len) return false; 

    // get number of digits that actually represent the number 
    int32 diff = str_len - non_zero_index; 

    // if difference less than 10 digits then no overflow will happened 
    if (diff < number_sizes[base]) return false; 
    // if difference greater than 10 digits then overflow will happened 
    if (diff > number_sizes[base]) return true; 

    // left digit in input and search strings 
    int8 left1 = 0, left2 = 0; 

    // if digits equal to 10 then loop over digits from left to right and compare 
    for (int32 i = 0; non_zero_index < str_len; non_zero_index++, i++) 
    { 
     // get input digit 
     left1 = value[non_zero_index]; 
     // get match digit 
     left2 = max_numbers[signExist][i]; 

     // if digits not equal then if left1 is greater overflow will occurred, false otherwise 
     if (left1 != left2) return left1 > left2; 
    } 

    // overflow won't happened 
    return false; 
} 

該算法可以優化所有整數類型,但與浮點工作,我必須做出新的符合IEEE浮點表示工作。

我覺得編譯器使用高效的算法來檢測比我其他的溢出,不是嗎?

+0

絕對....! – spender 2011-06-01 23:10:13

+0

以字符串形式比較數字對於大多數計算機來說不是一種有效的方法;他們更喜歡他們的數字不是文字形式。通常,大多數應用程序將數字文本轉換爲內部數字,然後處理內部數字。處理器像內部格式的數字,並且特別擅長以這種方式處理它們。 – 2011-06-01 23:28:13

+0

詞法分析器檢測到一個數字,所以它從它的後綴知道它的類型,現在它存儲文字形式並將其轉換爲數字形式,我的問題是它將存儲數字的類型是什麼?以及它如何檢測轉換的數字與文字形式的數字相匹配? – 2011-06-01 23:37:22

回答

6

編譯器處理它幾乎是最簡單的方式:他們轉換爲數字爲整數或浮點數爲適當。沒有法律規定編譯器不能將字符串轉換爲適當的其他表示。

但現在,考慮你的原始問題;如果你把數字和建立的例程作爲數字來對待它們,那麼呢?說,例如,一種算法,可以採取

6 + 5

和計算總和爲兩位數串11?將其擴展到其他操作,您可以直接計算32769是否大於32768

+0

只要沒有後綴,只要沒有後綴,C++數字就是'int',所以如果我執行INT_MAX + INT_MAX,那麼編譯器在將結果截斷爲目標類型限制之前將用於存儲結果的存儲是什麼? – 2011-06-01 23:27:12

+2

好,更大。但是你不需要這麼做就可以知道'INT_MAX' +'INT_MAX'>'INT_MAX'。有很多選擇,其中一些決定可能取決於底層硬件;例如,有沒有辦法檢測溢出?如果你堅持要求,我們可以對BigNum實施某種操作,交易空間和性能,以保證不會有實際溢出的機會。另外,在C++中,你不能保證編譯器甚至會檢測到溢出 - 編譯器可以處理它的一種方式是把責任交給你。 – 2011-06-01 23:37:34

+0

謝謝你查理。 – 2011-06-02 00:17:25

1

似乎簡單的編譯器將字符串表示轉換成一個整數在一個步驟中,然後比較針對所述類型的上界和下界中的二次工序。

我想不通爲什麼它會更好,比較字符串。

對於浮標,問題是更難由於精度和舍入。

0

我不知道最標準者使用要做到這一點有什麼特別的算法,但這裏有幾個選項可以工作:

  1. 編譯器可以嘗試使用現有的庫(例如,在C++ ,stringstream)嘗試將字符串轉換爲適當類型的編號。這可以用來檢查錯誤。

  2. 編譯器可以將字符串轉換爲非常高精度的數字格式(例如,128位整數),然後檢查每當從數字文字分配給基元類型時,可以在沒有演員的情況下適應該範圍。

+0

廣告1.實際上並不存在許多已知速度較慢的選項... :) – sehe 2011-06-01 23:17:31

0

眼看編譯器將不得不轉換爲積分/數字類型,無論如何,他們可以一樣好讓​​自己atoiatolatof函數產生一個錯誤當目標能力得到突破。

事先不需要對字符串進行操作,並在單獨的步驟中進行轉換。

我認爲,編譯器很可能會直接在其高度優化的解析器的語義操作中轉換爲整型。