2014-09-02 129 views
17

我通過這段代碼MSVC和鐺之間的行爲差​​異不解:應該如何用C++表示64位整數文字?

#include <iostream> 
#include <cstdint> 

int main() { 
    int64_t wat = -2147483648; 
    std::cout << "0x" << std::hex << wat << std::endl; 

    return 0; 
} 

的Visual Studio 2010,2012,和2013年(在Windows 7)的所有顯示:

0x80000000 

但叮噹503.0.40(在OSX上)顯示:

0xffffffff80000000 

根據C++標準,正確的行爲是什麼?文字應該是零擴展還是符號擴展到64位?

我知道int64_t wat = -2147483648LL;將導致在這兩個編譯器上的相同結果,但我想知道沒有文字後綴的正確行爲。

+0

@Paul R:「非感性」行爲僅在C89/90中存在,編譯器必須嘗試「int」,「long int」和「unsigned long int」 。包含無符號類型是一個糟糕的決定,它在C099和第一版C++(C++ 98)中被放棄了。現在編譯器必須按照寬度遞增的順序嘗試僅簽名的類型。在這種情況下,C++ 11的唯一區別是增加了long long int。它純粹是定量的。 – AnT 2014-09-02 14:51:52

+0

好的 - 謝謝 - 也許我在C和C++之間混了起來。FWIW無論如何,我總是添加明確的後綴,所以不必考慮行爲應該是什麼。 – 2014-09-02 14:53:57

回答

13

初始化左側的類型無關緊要。表達式-2147483648本身是獨立解釋的。

文字2147483648沒有後綴,這意味着編譯器會首先嚐試將其解釋爲int值。在你的平臺int顯然是一個32位的類型。值2147483648落在帶符號的32位整數類型的範圍之外。編譯器需要使用更寬的有符號整數類型來表示該值(如果有的話)(在intlong intlong long int序列中,最後一個從C++ 11開始正式提供)。但是,如果沒有足夠寬的帶符號整數類型是可用的,該行爲是未定義

在MSVC歷史long int具有相同的寬度int,儘管64位long long int也支持MSVC的更高版本。然而,即使在VS2013(它支持long long int)我得到

warning C4146: unary minus operator applied to unsigned type, result still unsigned 

響應您的初始化。這意味着MSVC仍然堅持古老的C89/90整數字面解釋規則(其中類型從intlong int,unsigned long int序列中選擇)。

請注意,MSVC不是官方的C++ 11編譯器。所以正式它不必嘗試long long int。這種類型在Pre-C++ 11語言中並不正式存在。從這個角度來看,MSVC在這種情況下沒有足夠大的有符號整數類型,並且行爲是未定義的。在未定義行爲提供的自由範圍內,使用C89/90規則進行整數字面解釋是非常合理的。

您也可以看看這個(-2147483648> 0) returns true in C++?

+0

我認爲這取決於您是否編譯爲C++ 11? – 2014-09-02 14:43:47

+0

@保羅R:怎麼樣?由於必須爲'int'和'long int'嘗試C++ 98「無後綴」整數文字。在MSVC中通常都有相同的寬度。 – AnT 2014-09-02 14:47:06

+0

我用於MSVC的命令行是'cl wat.cpp/EHsc',因此除了異常處理之外沒有特殊的標誌。我不認爲MSVC中存在C++ 11標誌。 – 2014-09-02 14:50:13