簡體   English   中英

C ++在unsigned int和unsigned long int之間的區別

[英]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一點點,並找到了這些參考。

  1. 在cppreference.com上鍵入文檔
  2. 在MSDN上為Visual Studio 2015 鍵入文檔
  3. GNU C / C ++的類型文檔 (作為G ++編譯器聲明C / C ++使用相同的默認類型實現,我在這里引用C doc)

我假設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相同。

所以我的問題如下:

  1. 對於無符號長64位,超出上限4,294,967,295的未定義行為或正確行為?
  2. 如果我有一個在Visual Studio中編譯的Windows系統上運行的應用程序,則basicall unsigned == unsigned long 對或錯?
  3. 如果我有一個在Linux / Windows上運行的GNU編譯器編譯的應用程序,我必須確保無符號long == unsigned intunsigned long == unsigned long long以避免數據溢出。 對或錯
  4. 如果我有一個可能由所有這些Visual Studio / GNU / Clang / Intel編譯器編譯的跨平台應用程序,我必須使用一堆預處理器清楚地對環境進行分類,以避免數據溢出。 對或錯

提前致謝。

編輯:感謝@PeterRuderman指出超出ceil值的無符號類型不是未定義的行為。

然后我的問題1將變為:

  1. 對於無符號長64位,將超出上限4,294,967,295導致自身環繞?

簡短的回答是, sizeof(unsigned)不能保證等於sizeof(unsigned long)但確實恰好在MSVC中。 如果您需要以獨立於平台的方式確定整數的大小,請使用<cstdint>的類型: uint32_tuint64_t 避免long使用便攜式代碼,這會導致很多麻煩。

另請注意,溢出無符號整數不是未定義的行為。 定義的行為是值環繞。 (例如std::numeric_limits< uint64_t >::max() + 43 == 42 )。 對於溢出是未定義行為的簽名類型,情況並非如此。

要回答最后一個問題,64位整數可以存儲[ 0,264 - 1]范圍內的值。 2 32 + 1不會導致纏繞。

在C ++標准中, unsigned int僅保證能夠表示065535值。 實際上,這相當於16位。 實現(即編譯器)可以提供具有更大范圍的unsigned int ,但不是必需的。

相比之下, unsigned long int保證能夠表示04294967295范圍內的值。 實際上,這相當於32位。 同樣,實現可以支持更大的范圍。

這些類型的范圍和大小是實現定義的。 實施必須滿足最低要求,並選擇其選擇的文件。

實現提供32位的unsigned intunsigned long int並不罕見。 或者,一個或兩個是64位。 正如您所注意到的,Visual Studio 2015的文檔指出unsigned intunsigned long int表示值04294967295

對於像g ++這樣可以針對一系列系統的編譯器,選擇通常由目標系統決定。 因此,對於32位系統,g ++的構建可能支持unsigned long不同范圍, unsigned long不是64位系統的構建。

回答你的問題

對於無符號長64位,超出上限4,294,967,295的未定義行為或正確行為?

雖然它可能無法產生您期望的結果,但它具有良好定義的行為。 C ++中的無符號整數類型使用模運算。 將轉換超出04294967295范圍的積分值(可支持更大范圍的類型),使其在該范圍內(數學上等效於重復加或減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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM