1 1 unsigned int的世界不簡單

2022-02-09 03:12:27 字數 1705 閱讀 4603

程式語言提供了很多的基本資料型別,比如char,int,float,double等等。在c和c++的世界中,還有一種型別,叫做無符號資料,修飾符位unsigned,比如今天要說的unsigned int。引入特殊的型別,一方面帶來了好處,一方面也留下了隱患。

上**:

#include #include int main()

結果為:

什麼?-1竟然大於1?從結果上看,的確是這樣的。為什麼從這樣呢?這樣從c++對同時包含有符號數與無符號數的表示式的處理說起。

當執行乙個運算時(如這裡的a>b),如果它的乙個運算數是有符號的而另乙個數是無符號的,那麼c語言會隱式地將有符號引數強制轉換型別為無符號數,並假設這兩個數都是非負的,來執行這個運算。這種方法對於標準的算術運算來說並無多大差異,但是對於像小於「」這樣的運算就可能產生非直觀的結果。

對應上面的例子,就是先把-1這個有符號數強制轉換成無符號數,再與1比較,並假設兩個數都是非負的。那麼-1轉換成無符號數是多少呢?在32位或者64位機器上,-1對應的無符號數是4 294 967 295,即32位的無符號數的最大值(umax),所以if中的條件總是為真。

要想這段**正常執行,我們需要怎麼辦呢?很簡單,把if語句改為if(a > (int)b)即可。這樣程式就會認為是兩個有符號數在進行比較,-1就不會隱式地轉換為無符號數而變成umax。

可能你已經有乙個問題,為什麼使用強制型別,把變數b的型別變成int程式就能正常,而-1轉換成無符號數為什麼會是4 294 967 295呢?這就得從整型資料在計算機中的表示和c語言對待強制型別轉換的方式說起。

我們知道,整數在計算機中通常是以補碼的形式存在的,而-1的補碼(用4個位元組儲存)為1111,1111,1111,1111。而c語言對於強制型別轉換是怎麼處理的呢?對大多數c語言的實現,處理同樣字長的有符號數和無符號數之間的相互轉換的一般規則是:數值可能會改變,但是位模式不變。也就是說,將unsigned int強制型別轉換成int,或將int轉換成unsigned int底層的位表示保持不變。

也就是說,即使是-1轉換成unsigned int之後,它在記憶體中的表示還是沒有改變,即1111,1111,1111,1111。我們知道在計算機的底層,資料是沒有型別可言的,所有的資料非0即1。資料型別只有在高層的應用程式才有意義,也就是說,同樣的儲存表示對於應用程式而言可能對應著不同的資料,例如1111,1111,1111,1111對於有符號數而言它表示-1,但對於無符號數而言,它表示umax,但是它們的底層儲存都是一樣的。現在你應該明白為什麼-1轉換成無符號數之後,就成了umax了吧。

上**,裡面有個show_byte函式,可以把從指標start開始的len個位元組用16進製制數的形式列印。

#include #include void show_bytes(unsigned char *start, int len)

int main()

結果為:

printf函式中,%u表示以無符號數十進位制的形式輸出,%d表示以有符號十進位制的形式輸出。通過show_bytes函式,我們可以看到,-1與4 294 967 295的底層表示是一樣的,它們的位全部都是全1,即每個位元組表示為ff。

unsigned int數相減時候的trick

假設是8位的unsigned int整數。乙個是x 134,乙個是y 246.首先拿過來就是計算它們的二進位制位 134 1000,0110b 246 1111,0110b 因為是無符號數,所以解釋成正數,也就意味著這樣的看似原碼的二進位制位就是補碼表示,也可以理解為符號位在第九位藏著乙個0.這裡主...

unsigned int 無符號整型的使用

有符號 int 和無符號 unsigned int unsigned int plus a 12 unsigned int plus b 13 int result c plus a plus b 0 plus a plus b 0 上面得到的結果 1 不應該是0的嗎?除錯可以發現 plus a p...

C語言之unsigned int和int的運算

首先先說明下 1 數值在計算機中是以補碼的形式儲存的。同時如果兩個補碼相加時,最高位也就是我們的符號位如果有進製,是需要丟棄的。正數的補碼是自己本身,負數的補碼是符號位為1,其餘位為該數絕對值的原碼按位取反,然後整個數再加1.2 如果乙個運算子兩邊的運算數型別不同,先要將其轉換為相同的型別,即較低型...