2010-02-28 120 views
12

我有以下數組,我需要手動操作位圖。C++:編譯器警告大unsigned int

const unsigned int BITS[32] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 
           2048, 4096, 8192, 16384, 32768, 65536, 131072, 
           262144, 524288, 1048576, 2097152, 4194304, 
           8388608, 16777216, 33554432, 67108864, 134217728, 
           268435456, 536870912, 1073741824, 2147483648}; 

不幸的是,在編譯時,我得到

警告:這個小數常量僅ISO C90

是無符號如何刪除這個?

+0

看到這個類似的問題:http://stackoverflow.com/questions/2347936/cant-get-ride-of-this-decimal-constant -is-unsigned-only-in-iso-c90-warning – 2010-02-28 23:33:10

+0

你爲什麼要這樣做?如果你認爲查找表比根據需要計算這些值要快,請再考慮一下...... – Nemo 2011-08-17 05:08:37

回答

15

默認情況下,C中的整數文字是類型「signed int」(編輯:但請參閱註釋以瞭解警告)。最後一個數字有太大而不能表示爲32位有符號整數,所以你需要用「U」後面添加它來告訴大家,這是一個無符號整數,編譯器,如:

2147483648U 

注意你也可以添加一個後綴「L」使其成爲「長」,但是在許多仍然是32位的系統中,因此不相關。

此外,還有寫這個代碼更容易出錯(和更容易閱讀的)的方式,與位移運算符:

const unsigned int BITS[32] = {1U, 1U<<1, 1U<<2, 1U<<3, 1U<<4, 
           /* and so on */ 
           1U<<31}; 

或者十六進制寫,如果你不由於某種原因不喜歡位移:

const unsigned int BITS[32] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 
           /* and so on */ 
           0x80000000U}; 
+0

爲什麼編譯器把它當作一個int來處理,而不是自動把它變成uint?特別是,它完全知道它將被存儲的類型。 – gruszczy 2010-02-28 20:54:35

+0

在很多情況下,您無法知道常量是什麼類型(例如,作爲varargs函數中的函數參數),因此必須明確指定它。令人困惑的是,有些類型需要在其他類型中明確指定,並且在具有不同int大小的系統上使相同的常量成爲不同類型。另外,因爲C從來沒有這樣的類型推斷,所以爲這種情況添加它會使解析器複雜化很多而沒有顯着的好處。 – 2010-02-28 21:01:30

+3

@gruszczy:在C89/90中,一個未經修飾的十進制常量必須被解釋爲'int','long'或'unsigned long'(無論哪個先適配)。在C99中,它必須被解釋爲「int」,「long」或「long long」(無論哪個先適合)。這是編譯器試圖通過此警告說的內容。顯然,在這個平臺上'long'與'int'具有相同的大小。編譯器基本上是這麼說的:「也許你正在試圖創建一個'帶符號的長連字符或者甚至'長連字符'常量,但是通過C89/90規則我必須使它成爲'unsigned long'。 – AnT 2010-02-28 21:28:26

6

你不變,必須得指定爲無符號,用

2147483648UL 

(UL =無符號長),或者乾脆

2147483648U 

爲一個unsigned int。

由於您的代碼現在是一個常量,默認情況下,它是一個普通的int,因此被標記爲unsigned int,它會生成警告。

+0

這很有效,非常感謝:-) – gruszczy 2010-02-28 20:50:21

+3

從腳踏實地講,錯誤不是來自事實的int)常量分配給一個unsigned int;這項任務是無關緊要的。錯誤是因爲「2147483648」的值太大而不能成爲帶符號的int,所以在首先生成帶符號的int常量時會出現溢出。 – 2010-02-28 20:55:53

+2

實際上,警告的真正原因是編譯器必須爲常量類型選擇'unsigned long'。 (注意,這個常量不是'unsigned int',它是'unsigned long'。)它必須在C89/90中專門選擇它,而不是選擇更大的簽名類型(它可能支持)或者跟隨C99規則和選擇「長期」。這是警告的內容,以及爲什麼涉及到「ISO C90」。例如,在C99中,一個沒有混合的十進制常量將永遠不會被賦予一個無符號類型。 – AnT 2010-02-28 21:32:32

1

沒有必要將數據類型定義爲無符號類型;

int variable_name=2147483648U; 

否則只是轉換十進制數爲十六進制...