1. 程式人生 > >c語言裡面TMin不能寫成-2147483648的原因

c語言裡面TMin不能寫成-2147483648的原因

C語言中,將TMin(32位有符號整數的最小值)寫成 -2147483647-1,而不是簡單地寫成 -2147483648 或 0x80000000 。這是為什麼呢?

首先,對於整數常量的定義:

    An integer constant begins with a digit, but has no period or exponent part. It may have a prefix that specifies its base and a suffix that specifies its type.

可見如果不發生溢位,整型常量的值總是非負數。如果前面出現符號,則是對整型常量使用的一元運算子,而不是整型常量的一部分。整型常量的實際型別取決於長度、基數、字尾字母和C語言實現確定的型別表示精度。具體的根據表一來確定。
  
其次

,看看C語言中limits.h中對於INT_MIN和INT_MAX的定義如下所示:

    #define INT_MAX 2147483647
    #define INT_MIN (-INT_MAX - 1)

那麼考慮到以上兩點,如果將TMin32寫成-2147483648並且將程式碼在一個32位的機器上面編譯,當編譯器遇到-X形式的數值,它首先會確定X的資料型別和值,然後取X的。

 ISO C90 ISO C99
十進位制(Decimal) 十六進位制(Hexadecimal)
十進位制(Decimal) 十六進位制(Hexadecimal)
int long unsigned unsigned long int unsigned long unsigned long
int long long long int unsigned long unsigned long long long unsigned long long

表一 根據C語言版本和常量的格式(十進位制和十六進位制),常量的資料型別是從上面表格裡選擇第一個合適(能表示常量)的型別。

 Word Size ISO C90 ISO C99
Expression -2147483648 0x80000000 -2147483648 0x80000000
32 64 unsigned long unsigned unsigned long long long unsigned unsigned

表二 根據C語言版本和常量的格式(十進位制和十六進位制),可以為這兩個表示式得到三種不同的資料型別,包括資料為正值的情況。

由於2147483648超過了int所能夠表示的範圍,編譯器就會再次選擇一種可以正確的表示此值的型別。然後它就會按照第一個表格(十進位制)的順序往下繼續嘗試型別,再假設編譯器採用的標準是ISO C90,int->long->unsigned,然後就發現unsigned是第一個合適的資料型別。正如我們知道的,2147483648和-2147483648在32位數值上擁有同樣的位表示,使得此常量的最終資料型別是unsigned且值為2147483648。這對於16進位制的0x80000000也是相同的結果。

對於64位來說十進位制和十六進位制會分別選擇long(-2147483648)和unsigned(2147483648)。而ISO C99的情況則是按照上述規則資料型別為long long才能容納2147483648。

最後結論是:-214748364832位機器裡使用ISO C90進行編譯,會先將2147483648看成是一個unsigned,再對2147483648進行無符號的加法逆元計算(見csapp第二版56頁),得到結果是:
(-uw2147483648) = 2w - x = 232 - 231 = 231 = 2147483648。

所以對於下面的表示式:

    int result = -2147483648 < 2147483647;

在32位機器裡面使用ISO C90進行編譯, result = 0。