?

一、自動類型轉換

??? 一般來說,同一句語句或表達式應該使用同一種類型的變量和常量。如果使用了多種類型的變量和常量(類型混用),C 會自動把它們轉換成同一種類型。自動類型轉換為我們寫程序提供了方便,卻也帶來了危機。因粗心大意而造成的類型混用也許會導致程序運行出錯。以下是自動類型轉換的基本規則:

??? 1. 在表達式中,char 和 short 類型的值,無論有符號還是無符號,都會自動轉換成 int 或者 unsigned int(如果 short 的大小和 int 一樣,unsigned short 可表示的最大值就大于 int,在這種情況下,unsigned short 被轉換成 unsigned int)。因為它們被轉換成表示范圍更大的類型,故而我們把這種轉換稱之為“升級promotion)”。

??? 2. 按照從高到低的順序給各種數據類型分等級,依次為:long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int 和 int。這里有一個小小的例外,如果 long 和 int 大小相同,則 unsigned int 的等級應位于 long 之上。char 和 short 并沒有出現于這個等級列表,是因為它們參與運算時就應該已經被升級成了 int 或者 unsigned int。

??? 3. 在任何涉及兩種數據類型的操作中,它們之間等級較低的類型會被轉換成等級較高的類型。

??? 4. 在賦值語句中,= 右邊的值在賦予 = 左邊的變量之前,首先要將右邊的值的數據類型轉換成左邊變量的類型。也就是說,左邊變量是什么數據類型,右邊的值就要轉換成什么數據類型的值。這個過程可能導致右邊的值的類型升級,也可能導致其類型降級demotion)。所謂“降級”,是指等級較高的類型被轉換成等級較低的類型。

??? 5. 作為參數傳遞給函數時,char 和 short 會被轉換成 int,float 會被轉換成 double。使用函數原型可以避免這種自動升級。這點我以后會詳細講解。

??? 類型升級通常不會有什么問題,但是類型降級卻會帶來不少問題。例如:

??????? char ch = 1222;

1222 降級為 char,但 char 無法表示 1222。再如:

??????? int j = 22.2;

22.2 降級為 int,小數部分被截斷。


二、類型轉換運算符

??? 使用類型轉換運算符可以指定我們想要進行的類型轉換。類型轉換運算符由括號和類型名組成:

??????? (type)

其中,我們應該用我們想轉換成的類型替換掉 type,例如:(long), (unsigned long)。

??? 類型轉換運算符應該放在值的前面:

??????? int i = (int)1.1 + (int)2.2;

1.1 在加法運算前就因為類型轉換運算符而降級為 int,其值變為 1。類似地,2.2 也降級為 int,其值變為 2。又如:

??????? int j = 20;
??????? double k = (double)j;

j 的值被轉換成 double,然后用于初始化 k。


三、小例子

??? #include <stdio.h>

??? int main(void)
??? {
??????? char ch;
??????? int i;
??????? float fl;
??????? double db;

??????? db = fl = i = ch = 'C';???????????????? /* 10 */
??????? printf("ch=%c, i=%d, fl=%2.2f, db=%2.2f\n", ch, i, fl, db);

??????? ch = ch + 1;??????????????????????????? /* 13 */
??????? i = db + fl + 2 * ch;?????????????????? /* 14 */
??????? fl = 2.0 * ch + i;????????????????????? /* 15 */
??????? db = 22 * i + ch - fl;????????????????? /* 16 */
??????? printf("ch=%c, i=%d, fl=%2.2f, db=%2.2f\n", ch, i, fl, db);

??????? i = 666.6 + 777.7;????????????????????? /* 19 */
??????? printf("Now i = %d\n", i);
??????? i = (int)666.6 + (int)777.7;??????????? /* 21 */
??????? printf("Now i = %d\n", i);

??????? return 0;
??? }

我的系統中,char 是 8 位的,int 是 32 位的。輸出為:

??? ch=C, i=67, fl=67.00, db=67.00
??? ch=D, i=270, fl=406.00, db=5602.00
??? Now i = 1444
??? Now i = 1443

第 10 行,'C' 的值被轉換為 char,然后賦值給 ch。ch 的值被轉換成 int,然后賦值給 i。以此類推。

第 13 行,= 右邊的 ch 的值先被轉換成 int,然后和 1 相加,得到 32 位的 int 類型整數 68。最后,68 降級為 char,然后賦值給 ch。在 ASCII 中,D 的編碼是 68。

第 14 行,ch 的值被轉換成 int,然后和 2 相乘得 136。fl 的值被轉換成 double,然后和 db 相加,其和再與轉換成 double 的 136 相加得 270.0 。最后,270.0 被轉換成 int,然后賦值給 i。

第 15 行,ch 的值被轉換成 double,然后和 2.0 相乘,i 的值被轉換成 double,然后和前面得到的乘積相加,相加的得數被轉換成 float,然后賦值給 fl。

第 16 行,22 和 i 相乘得 5940,ch 的值被轉換成 int,然后和 5940 相加得 6008,然后,6008 被轉換成 float,再和 fl 相減得 5602.0f,最后 5602.0f 被轉換成 double,再賦值給 db。

第 19 行,666.6 和 777.7 相加得 1444.3,然后 1444.3 被降級成 int,再賦值給 i。

第 21 行,類型轉換運算符把 666.6 和 777.7 轉換為 int,得 666 和 777,它們相加得 1443,最后,1443 被賦值給 i。

注意,類型轉換改變的是值的類型,而不是對象的類型,對象的類型自始至終都是不變的。例如:

??? i = fl + ch;

ch 的值被轉換成 float,而 ch 本身仍然是 char 類型的變量。

參考資料:C Primer 5th Edition
??????????The C Programming Language 2nd Edition
????????? C99 標準