簡體   English   中英

2^32 - 1 不是 uint32_t 的一部分?

[英]2^32 - 1 not part of uint32_t?

這是編譯輸出讓我哭的程序:

#include <inttypes.h>

int main()
{
        uint32_t limit = (1 << 32) - 1; // 2^32 - 1 right?
}

這是編譯輸出:

~/workspace/CCode$ gcc uint32.c 
uint32.c: In function ‘main’:
uint32.c:5:29: warning: left shift count >= width of type [-Wshift-count-overflow]
         uint32_t limit = (1 << 32) - 1; // 2^32 - 1 right?

我認為(1 << 32) - 1等於 2^32 - 1 並且 32 位的無符號整數范圍從 0 到 2^32 - 1,是不是這樣? 我哪里做錯了?

警告是正確的,32 位數字中的最高位是第 31 位(0 索引),因此溢出前的最大移位是1 << 30 (30 因為符號位)。 即使您在某個時候執行-1 ,也必須存儲1 << 32的結果,並將其存儲在一個int (在這種情況下恰好是 32 位)。 因此,您會收到警告。

如果您確實需要獲得32 bit unsigned int的最大值,則應該以簡潔的方式進行:

#include <stdint.h>

uint32_t limit = UINT32_MAX;

或者更好的是,使用 c++ 限制頭文件:

#include <limits>
auto limit = std::numeric_limits<uint32_t>::max();

你有兩個錯誤:

  • 1int類型,因此您將初始值計算為int ,而不是uint32_t
  • 正如警告所說,移位運算符的移位參數必須小於類型的寬度。 如果int為 32 位或更少,則1 << 32未定義的行為 (uint32_t)1 << 32也將是未定義的。

(另外,請注意1 << 31也是未定義的行為,如果int是 32 位,因為溢出)

由於算術無論如何都是以2^32為模完成的,因此一種更簡單的方法就是

uint32_t x = -1;
uint32_t y = (uint32_t)0 - 1; // this way avoids compiler warnings

嘗試計算目標常量時,編譯器在您的示例中內部使用 int 。 想象一下,rhe 編譯器沒有任何可用的優化,而是為您的班次生成匯編程序。 對於 32 位 int 移位指令,數字 32 會很大。

此外,如果您想設置所有位,請使用 ~0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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