C中有符號數與無符號數轉化之間的危險

2021-06-19 21:06:22 字數 1459 閱讀 2535

無符號數與有符號數之間存在著很多細節問題,稍有不慎就可能導致程式出現不可預料的錯誤。如果說是在長度相同的數值型別之間相互轉化或者向長度比較短的資料轉化是沒有問題的,結果都是已定義的:多餘的位將被簡單的丟棄。但是,一旦需要向長度更長的資料型別轉化這個問題就會變得十分蹊蹺。例如編譯器在轉化char型別到int型別時,需要作出選擇:應該講字元作為有符號數還是應該無符號數處理?如果是前一種情形,編譯器在將char型別擴充套件到int型別時,應該同時複製符號位;而如果是後一種情況,編譯器只需要在多餘的位上直接填充0即可。

下面是自己總結的乙個小陷阱,如果將乙個較短的數值轉化為乙個較長的數值的時候,尤其是轉化為無符號數的情形下,問題就會出現。因為數值會首先轉化為較長型別的有符號數,然後再同型別轉化為無符號數。例如:c是乙個字元變數,使用(unsigned)c就可以得到與c等價的無符號整數,這是失敗的。因為在將字元c轉化為無符號整數時,c將首先被轉化為int型整數,而此時可能得到非預期的結果。

正確的方式是使用(unsigned char)c,因為乙個unsigned char型別的字元在轉化為無符號整數時無需首先轉化為int型整數,而是直接進行轉化。

下面是我在visual studio 2008下測試的結果。

#include int main()

上述**執行結果為:

可以發現vs2008的編譯器資料轉化時是將符號位擴充套件出去的。注意unsigned int d = (unsigned int )a語句,將a首先轉化為int,此時為-2,將-2轉化為unsigned int其實沒有起作用,列印的時候仍然是按照有符號數列印的。

總結:在執行短資料向高資料轉化時,首先在本型別上完成無符號轉化,然後向高資料轉化。這樣做的目的是多餘位直接補0.

發現乙個問題:

#include int main()

執行結果為:

如果同型別之間的轉化則出現了問題

#include int main()

執行結果為:

猜測:這就跟printf跟的格式化引數有關,使用%d則認為最高位為符號位,列印出來的結果按照有符號數列印,如果想列印出無符號數應該使用格式化引數%u.

#include int main()

執行結果為:

有符號數與無符號數

關於有符號數和無符號數的一些重要知識點,包括它們在記憶體中的儲存方式 互相轉換 越界計算等。大家肯定都知道,對於有符號數,資料型別的最高位用於標示資料的符號,最高位為1表示負數,最高位為0表示正數,那麼今天我們主要就此討論乙個問題 在計算機內部具體是如何表示有符號數呢?在計算機內部是通過補碼的方式來...

C語言中 有符號數 無符號數 整數溢位

c語言中存在兩種整數算術運算,有符號型和無符號型。無符號數運算 所有無符號數運算都是以2的n次方為模,n是結果中的位數 所以它不存在運算時的沒有那種所謂的 溢位 當它超過範圍時,從零開始重新計數!當乙個無符號數和有符號數相加的時候,有符號數會自動轉化為無符號數參與運算!有符號數運算 是可能發生 溢位...

C語言中 有符號數 無符號數 整數溢位

includevoid main 這個的結果134,而不是我之前認為的很大的正數,實際上需要注意的是 1 0xffffffff 被提公升為unsigned int後是乙個差1就溢位的unsigned int,所以相加後結果是134。但是如果l 10000,那麼結果就真是乙個很大的正數了,因為不涉及溢...