接下來是不同型別之間的強制轉換。當把乙個高容量的型別強制轉換為低容量的型別時,會發生截斷:丟棄二進位制的高位,只保留低位(二進位制的左邊為高位,右邊為低位);而把低容量型別強制轉換成高容量型別時,會發生擴充套件:在二進位制的高位左邊繼續填充數字。擴充套件分為兩類:零擴充套件和符號擴充套件。下面看**示例。
1、截斷
#include int main(void)
結果:
a = 257, b = 1
a = 0x101, b = 0x1
0x0101被分成兩部分,高位的01和低位的01,char型別只能容納乙個位元組,於是取低位的乙個位元組後,結果是0x01。
再看乙個:
#include int main(void)
結果:
a = -24368, b = -48
a = 0xffffa0d0, b = 0xffffffd0
a: 2, b: 1
雖然截斷後的結果是一致的,但是這裡的printf似乎是按四個位元組來列印負數的十六進製制。
2、擴充套件
#include int main(void)
結果:
a = 63222, b = 63222
a = 0xf6f6, b = 0xf6f6
a: 2, b: 4
顯然,雖然列印出來的a和b的二進位制表示相同,但是用sizeof運算子計算長度時,發現b占用了4個位元組,所以b的實際十六進製制為:0x0000f6f6。這表明,無符號數的擴充套件採用0來填充高位,這就是所謂的零擴充套件。
另外,我發現printf函式列印十六進製制時,自動忽略高位的0。
有符號數呢?
#include int main(void)
結果:
a = -68, b = -68
a = 0xffffffbc, b = 0xffffffbc
a: 1, b: 2
呃,又被嚇到了,我不禁懷疑printf函式列印十六進製制時存在bug:sizeof顯示a的確只佔乙個位元組,所以十六進製制只列印0xbc就夠了,為毛還要加上前面一堆f?同理,b的話,0xffbc就夠了。。
不過至少,我們知道低容量的char向高容量的short擴充套件時,如果其二進位制最高位是1,那麼擴充套件後的高位用1來填充,這就是所謂的符號擴充套件。
我再驗證一下有符號的正數:
#include int main(void)
結果:
a = 68, b = 68
a = 0x44, b = 0x44
a: 1, b: 4
恩,雖然也是用0來填充高位,但此時0應被視為正號,仍是符號擴充套件。
總結上面printf函式的這個小「bug」讓我不禁這樣猜想:是不是在做型別轉換時,無論是截斷還是擴充套件,先統一變成四個位元組,若不足四個位元組,則採用相應的擴充套件。
若列印十進位制,則從右到左讀取相應的型別長度,然後停止讀取並將讀取的資料列印成十進位制;但是列印十六進製制時,在讀取了足夠的型別長度後,若讀到0則停止讀入,若讀到1則繼續讀入,直到讀夠4個位元組。
那麼最後,符號轉換和型別轉換一起上會怎樣?
#include int main(void)
結果:
a = -1, a = 0xffffffff
b = 65535, b = 0xffff
c = 4294967295, c = 0xffffffff
對於b,是先把a由signed short轉換成unsigned short,再轉換成int;而c的話,先做型別轉換,再由signed轉換成unsigned。我們看到結果是不同的,理由在上面說過了。另外,
unsigned等價於unsigned int。
現在我們來研究一下有符號數和無符號數運算的問題。
c語言規定,如果參與運算的兩個數乙個是有符號的另乙個是無符號的,那麼有符號數會被隱式的強制轉換成無符號數,並假設兩個數都是非負數。
這條規則對於算數運算來說,不會導致什麼區別,也就是沒什麼負面作用。然而對於邏輯運算可能會產生意外。
如:-1 < 0u
表面上看沒什麼錯,但這個運算的結果是0,即false。。因為-1被轉換成無符號數後就是4294967295u,它當然不可能小於0u。。。
在比如:2147483647u > -2147483647 - 1
結果也是錯的,因為-2147483648轉換成無符號數後是2147483648。
C語言筆記之資料型別(一)
在 計算機眼裡的數字 這篇文章中,我曾提到,位元組是計算機最小的可定址的單位,位址對應的是乙個個位元組,而不是位元組的每個位。這樣編址的原因很簡單 單個的位所能表示的資訊量太少了,只有兩種狀態0和1,只有把足夠多的位組合起來才能表示足夠豐富的資訊。那麼為什麼一定要是8呢?因為大家都這麼做。好吧,肯定...
C語言初學(二)資料型別
c語言資料型別包括基本型別 整型 字元型 實型 列舉型別 指標型別 構造型別 陣列型別 結構體型別 共用體型別 以及空型別四大型別。基本資料型別 其值不可以再分解為其他型別的型別,類似於細胞 構造資料型別 採用構造方法構造乙個或多個資料型別 指標型別 指標是一種特殊的,同時又具有重要作用的資料型別 ...
二 C語言的資料型別
c語言沒有字串型別 include intmain 資料型別 是把一組性質相同的值的集合及定義在此集合上的一些操作的總稱簡單來說就是為了節省計算機的記憶體空間,舉個例子 比如說我要在計算中存數字1 和 數字 344654745,它們佔的空間是不一樣的,1的二進位制是 0001 344654745的二...