為什么不建議使用無(wú)符號(hào)整型,無(wú)符號(hào)整型能產(chǎn)生哪些bug?
《C專(zhuān)家編程》有這么幾行代碼。
#include一個(gè)數(shù)組,一個(gè)宏定義,宏的作用就是計(jì)算數(shù)組的元素個(gè)數(shù)。int array[] = {23, 34, 12, 17, 204, 99, 16}; #define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0])) int main() { int d = -1, x; /* ... */ if (d <= TOTAL_ELEMENTS - 2) x = array[d + 1]; /* ... */ return 0; }
主函數(shù)里面d初始化成-1,判斷語(yǔ)句中用 d 跟 TOTAL_ELEMENTS - 2做比較,如果成立,則給 x 賦值。
代碼很簡(jiǎn)單,乍一看,-1 確實(shí)小于 5,于是判斷語(yǔ)句肯定成立。
問(wèn)題就出在了這邊。
d屬于有符號(hào)整型,TOTAL_ELEMENTS因?yàn)槭莝izeof的求值結(jié)果,所以它屬于無(wú)符號(hào)整型,把這兩個(gè)放在一起運(yùn)算,很顯然屬于混合運(yùn)算。
一個(gè)是有符號(hào)一個(gè)是無(wú)符號(hào),編譯器默認(rèn)把有符號(hào)數(shù)轉(zhuǎn)換成無(wú)符號(hào)數(shù),接下來(lái)我們可以算一下。
-1的二進(jìn)制是這樣的:
10000000 00000000 00000000 00000001
因?yàn)樨?fù)數(shù)在內(nèi)存中是以補(bǔ)碼的形式存放,所以先轉(zhuǎn)換成反碼,再轉(zhuǎn)換成補(bǔ)碼。
11111111 11111111 11111111 11111110 11111111 11111111 11111111 11111111
把它轉(zhuǎn)換成無(wú)符號(hào)數(shù)字,就是最高位不再表示符號(hào)位,全部用來(lái)表示實(shí)際大小。
借助下計(jì)算器,-1轉(zhuǎn)換成無(wú)符號(hào)數(shù)就是這么大:
4294967295
所以判斷語(yǔ)句肯定不成立。
只要編譯器的sizeof返回的是無(wú)符號(hào)整型,那么這個(gè)bug就一直存在。 ?
對(duì)無(wú)符號(hào)類(lèi)型的建議:
盡量不要在你的代碼中使用無(wú)符號(hào)類(lèi)型,以免增加不必要的復(fù)雜性。尤其是,不要僅僅因?yàn)闊o(wú)符號(hào)數(shù)不存在負(fù)值(如年齡、國(guó)債)而用它來(lái)表示數(shù)量。
盡量使用像 int 那樣的有符號(hào)類(lèi)型,這樣在涉及升級(jí)混合類(lèi)型的復(fù)雜細(xì)節(jié)時(shí),不必?fù)?dān)心邊界情況(如 -1 被翻譯為非常大的正數(shù))。
只有在使用位段和二進(jìn)制掩碼時(shí),才可以用無(wú)符號(hào)數(shù)。應(yīng)該在表達(dá)式中使用強(qiáng)制類(lèi)型轉(zhuǎn)換,使操作數(shù)均為有符號(hào)數(shù)或者無(wú)符號(hào)數(shù),這樣就不必由編譯器來(lái)選擇結(jié)果的類(lèi)型。
嵌入式開(kāi)發(fā)中使用無(wú)符號(hào)的場(chǎng)景很多,操作地址、寄存器等等,尤其是做單片機(jī)等等一些底層開(kāi)發(fā),隨處可見(jiàn) unsigned 字樣,這也是由硬件特性決定。使用的時(shí)候多加注意,尤其是做一些基本運(yùn)算的時(shí)候。
審核編輯:湯梓紅
-
嵌入式
+關(guān)注
關(guān)注
5059文章
18973瀏覽量
302040 -
寄存器
+關(guān)注
關(guān)注
31文章
5294瀏覽量
119816 -
編程
+關(guān)注
關(guān)注
88文章
3565瀏覽量
93536 -
代碼
+關(guān)注
關(guān)注
30文章
4722瀏覽量
68234
原文標(biāo)題:為什么不建議使用無(wú)符號(hào)整型
文章出處:【微信號(hào):學(xué)益得智能硬件,微信公眾號(hào):學(xué)益得智能硬件】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論