[英]C++ difference between unsigned int and unsigned long int
我正在使用Visual Studio Compiler在Windows上進行C ++開發,特別是Visual Studio 2015 Update 3。
對於一些DSP相關的工作,我使用unsigned int / unsigned long數據類型。 我想知道這兩個內置的C / C ++類型有什么區別。
我搜索了谷歌和SO一點點,並找到了這些參考。
我假設cppreference文檔是ISO C ++ 11標准的總結。 因此,從“標准” 無符號和無符號int是16/32位,取決於LP / ILP 32/64數據模型, 而無 符號長整數和無符號長整數是32/64位,具體取決於LP / ILP 32/64數據模型。
對於MSDN和GNU文檔,他們都聲明unsigned int / unsigned long使用32位實現,並且可以保存最多4,294,967,295的值。 然而,GNU文檔還聲明,根據您的系統,unsigned long可以是64位,其中它與unsigned long long int相同。
所以我的問題如下:
提前致謝。
編輯:感謝@PeterRuderman指出超出ceil值的無符號類型不是未定義的行為。
然后我的問題1將變為:
簡短的回答是, sizeof(unsigned)
不能保證等於sizeof(unsigned long)
但確實恰好在MSVC中。 如果您需要以獨立於平台的方式確定整數的大小,請使用<cstdint>
的類型: uint32_t
和uint64_t
。 避免long
使用便攜式代碼,這會導致很多麻煩。
另請注意,溢出無符號整數不是未定義的行為。 定義的行為是值環繞。 (例如std::numeric_limits< uint64_t >::max() + 43 == 42
)。 對於溢出是未定義行為的簽名類型,情況並非如此。
要回答最后一個問題,64位整數可以存儲[ 0,264 - 1]范圍內的值。 2 32 + 1不會導致纏繞。
在C ++標准中, unsigned int
僅保證能夠表示0
到65535
值。 實際上,這相當於16位。 實現(即編譯器)可以提供具有更大范圍的unsigned int
,但不是必需的。
相比之下, unsigned long int
保證能夠表示0
到4294967295
范圍內的值。 實際上,這相當於32位。 同樣,實現可以支持更大的范圍。
這些類型的范圍和大小是實現定義的。 實施必須滿足最低要求,並選擇其選擇的文件。
實現提供32位的unsigned int
和unsigned long int
並不罕見。 或者,一個或兩個是64位。 正如您所注意到的,Visual Studio 2015的文檔指出unsigned int
和unsigned long int
表示值0
到4294967295
。
對於像g ++這樣可以針對一系列系統的編譯器,選擇通常由目標系統決定。 因此,對於32位系統,g ++的構建可能支持unsigned long
不同范圍, unsigned long
不是64位系統的構建。
回答你的問題
對於無符號長64位,超出上限4,294,967,295的未定義行為或正確行為?
雖然它可能無法產生您期望的結果,但它具有良好定義的行為。 C ++中的無符號整數類型使用模運算。 將轉換超出0
到4294967295
范圍的積分值(可支持更大范圍的類型),使其在該范圍內(數學上等效於重復加或減4294967296
[注意最后一位數])。 換句話說,它將“環繞”。
如果我有一個在Visual Studio中編譯的Windows系統上運行的應用程序,則basicall unsigned == unsigned long。 對或錯?
假設Visual Studio 2015確實如此,正如您鏈接的文檔所說的那樣。 未來的Microsoft產品可能會或可能不會 - 這是一個實施決策。
如果我有一個在Linux / Windows上運行的GNU編譯器編譯的應用程序,我必須確保無符號long == unsigned int或unsigned long == unsigned long long以避免數據溢出。 對或錯
實際上,是的。
只有在移植依賴於這些假設的代碼時才會出現這種情況。
您可以使用某些技術,因此您的代碼不依賴於此類假設。 例如,您可以安全地檢測涉及兩個unsigned
值的操作何時溢出或下溢,並采取措施以產生所需的結果。 如果適當地檢查所有操作,則可以避免依賴特定大小的類型。
如果我有一個可能由所有這些Visual Studio / GNU / Clang / Intel編譯器編譯的跨平台應用程序,我必須使用一堆預處理器清楚地對環境進行分類,以避免數據溢出。 對或錯
不完全正確。 實際上,往往是真的。
如果您的代碼符合標准C ++的領域,那么有一些技術可以避免這樣做(就像我上面提到的那樣,能夠避免依賴於無符號類型的大小)。
如果您的代碼使用或提供了標准C ++之外的函數(例如Windows API,不符合C ++標准的posix函數),那么它通常是必要的。 即使在這些情況下,也可以避免這種情況。 例如,將使用Windows API的函數的版本放在與使用posix的版本不同的源中。 並配置構建過程(makefile等) - 例如,如果構建用於windows,則不要在unix版本中編譯或鏈接。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.