c支持所有數據類型的有符號與無符號運算,盡管c標准沒有明確指定某種有符號數的表示,但是幾乎所有的機器都使用二進制補碼
大多數數字默認是有符號的,當咱們聲明一個12345或者0x123,這其實都是有符號的
c在同時包含有符號和無符號的運算,c會把有符號的運算數隱含轉換成無符號的運算數(只要含有無符號的數,其他的有符號的數都會被隱含的轉換成無符號的數)
一、創建無符號的常量
在常量的后邊加上后綴字符“U”或者“u”,比如 12345U 或者 0x123u(大小寫都行)
二、轉換
c允許有符號與無符號之間的轉換,原則是基本的位表示保持不變;
1.無符號轉換成有符號,效果就是應用了函數U2Tw,其中w表示數據類型的位數
U2Tw = -xw-12W + X;
,從這里可以看出,當 0 <= x < 2w-1的時候是正數,則轉換的過程中保持不變; 當 x >= 2w-1的時候,結果是x - 2w,
下面是示意圖:
結論:
1>. 對於小的數(< 2w-1):從無符號到有符號的轉換將保留數字的原值;
2>.對於大的數(>= 2w-1):從無符號到有符號的轉換,數字將被轉換為一個負數值
比如:2147483648U,在輸出的時候為什么是-2147483648,
過程:因為2147483648 >= 2(32-1),也就是說,它是大的數(>= 2w-1),按照U2Tw的規則,2147483648 - 232 = -2147483648
2.從有符號轉換成無符號,效果就是應用了函數T2Uw,其中w表示數據類型的位數
T2Uw = xw-12W + X;
從這里可以看出,當 x >= 0的時候是正數,則轉換的過程中保持不變; 當 x < 0的時候是負數,結果是x + 2w
下面是示意圖:
結論:
1>.非負數:保持不變
2>.負數:被轉變成了大的正數,也就是x + 2w
比如:-1
過程:根據函數規則,負數 -1 + 232 = -4294967297
三、注意事項(下面的觀點有誤)
1.先看幾個練習題:
a. -2147483648 == 2147483648U
b. -2147483648 < -21474836487
c. (unsigned) -2147483648 < -21474836487
d. - 2147483648 < 21474836487
e.(unsigned) -2147483648 < 21474836487
示例:
前面提到過我們創建的數字常量啥的默認都是有符號的,聲明無符號的常量在后邊加上后綴“U”或者“u”,當兩個數進行運算時,只要有無符號數,那么另一個有符號數也會被隱含的轉換成無符號數,還有一點,那就是針對超出系統指定位數正數范圍的數,在轉換的時候,高位是要被舍去的,比如:在8位機器上邊,最大的無符號正數也才255,那300,在比較的時候怎么轉換呢?
比如 (unsigned) -127 < 300
過程:首先有unsigned聲明是無符號的,那么整個運算類型是無符號的,那先來轉換一下,-127(有符號轉無符號T2Uw)轉成無符號的是 -127 + 28 = 129; 那300呢?本身它是個正整數,但是它超出系統8位機最大的unsigned int值(INT_MAX = 255),咱們先把300轉成2進制(100101100),從這個二進制可以看出,它是9位,根據系統位數,超出最大范圍的數,二進制的最高位要被舍去,保留8位,結果是00101100 = 44,結果可想而知(unsigned) -127(129) < 300(44) 的結果是0
分析練習題:
a. -2147483648 == 2147483648U;2147483648U后綴是“U”,則根據規則 該運算的類型是無符號的,-2147483648根據規則轉換成無符號的(-2147483648 + 232 = 2147483648 ),而2147483648由於剛好等於231,而2147483648U它是無符號的,
b. -2147483648 < -21474836487;該運算是有符號類型,同事有符號且是負數的進行比較,這里不難看出來其實-2147483648 > -21474836487,所以結果是0