C中關於unsigned的陷阱

引言-一個誤解的誕生:

<<C++ Primer第五版>>中關於含有無符號類型的表達式的描述中有這樣一句話:
當一個算數表達式中既有無符號數又有int值時,那個int值就會轉換成無符號數。把int轉換成無符號數的過程和把int值直接賦給無符號變量一樣:

感覺Primer裏的語言描述就是這樣,很容易讓人誤解,但是當你犯錯後,再回頭看,又發現人也確實沒講錯。

首先,我們看看這個容易讓人誤解的第一句話:
當一個算數表達式中既有無符號數又有int值時,那個int值就會轉換成無符號數。 很多人在沒有讀懂第二句話的情況下理所當然就會把第一句話理解成:
如果一個算數表達式中既有無符號數又有int值,那麼如果出現負數的話,會把他轉換成一個無符號數的大小,再繼續進行運算;em…大錯特錯!雖然它確實已變成了無符號類型。

我們執行一下程序:

#include <iostream>
using namespace std;
int main()
{
 unsigned int a = 5;
 int b = -1;
 cout << a + b << endl;
}

如果按照上面的思路,那應該是5+4294967292。但是程序運行後的結果卻是4,咦?這不沒進行轉換嗎?
那是不是真的沒有進行轉換呢?
我們再執行下以下程序:

#include <iostream>
using namespace std;
int main()
{
 unsigned int a = 1;
 int b = -5;
 cout << a + b << endl;
}

如果沒有進行轉換,那麼結果應該是-4,但是程序運行後,結果卻是:4294967292

哇!這究竟是怎麼一回事?

解釋

好,讓我們忘掉以前的理解,重新分析Primer的兩句話:

當一個算數表達式中既有無符號數又有int值時,那個int值就會轉換成無符號數。
這句話其實沒什麼好解釋的,也就是有符號類型會被類型轉化成無符號類型
把int轉換成無符號數的過程和把int值直接賦給無符號變量一樣。
這句話纔是最重要的,其意思可以理解成將有符號類型類型轉化成無符號類型的過程並沒有改變數的位,也就是其在內存中的二進制形式,只是改變了其看待方式(類型)

什麼是看待方式?
我們分析下不同的看待方法,會有什麼樣的不同:
比如二進制數:1111,1111,1111,1111
對於int: 它是補碼,表示 -1
對於unsigned int: 它是 4294967292
也就是說同一個二進制數,不同的類型,其表示的值是不同的。

但是我們進行運算時,機器用的仍然是用的二進制數。也就是說機器運算時有符號數與無符號數的運算並沒有什麼區別,而不能以-1變成了4294967292來看待。

總結
所以我們大可以不必區分一個計算式中是有符號還是無符號數,其實他們的機器運算是完全一樣的。只不過我們對於它的運算結果-這個二進制數需要以不同的方式來看待它。當結果是正數時,也沒有區別,但當其爲負數,我們需要把他當成無符號數再看待。

備註:
返回值類型爲size_t,其本質是unsigned int,所以需要特別注意!比如sizeof(),strlen()等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章