6.3 類型轉換

C語言學習欄目目錄

目錄

強制類型轉換運算符


通常,在語句和表達式中應使用類型相同的變量和常量。但是,如果使用混合類型,C 不會像 Pascal那樣停在那裏死掉,而是採用一套規則進行自動類型轉換。雖然這很便利,但是有一定的危險性,尤其是在無意間混合使用類型的情況下(許多UNIX系統都使用lint程序檢查類型“衝突”。如果選擇更高錯誤級別,許多非UNIX C編譯器也可能報告類型問題)。最好先了解一些基本的類型轉換規則。

1.當類型轉換出現在表達式時,無論是unsigned還是signed的char和short都會被自動轉換成int,如有必要會被轉換成unsigned int(如果short與int的大小相同,unsigned  short就比int大。這種情況下,unsigned  short會被轉換成unsigned int)。在K&R那時的C中,float會被自動轉換成double(目前的C不是這樣)。由於都是從較小類型轉換爲較大類型,所以這些轉換被稱爲(promotion)。

2.涉及兩種類型的運算,兩個值會被分別轉換成兩種類型的更高級別。

3.類型的級別從高至低依次是long  double、double、float、unsignedlonglong、long long、unsigned long、long、unsigned int、int。例外的情況是,當long 和 int 的大小相同時,unsigned int比long的級別高。之所以short和char類型沒有列出,是因爲它們已經被升級到int或unsigned int。

4.在賦值表達式語句中,計算的最終結果會被轉換成被賦值變量的類型。這個過程可能導致類型升級或降級(demotion)。所謂降級,是指把一種類型轉換成更低級別的類型。

5.當作爲函數參數傳遞時,char和short被轉換成int,float被轉換成double。後面,函數原型會覆蓋自動升級。類型升級通常都不會有什麼問題,但是類型降級會導致真正的麻煩。原因很簡單:較低類型可能放不下整個數字。例如,一個8位的char類型變量儲存整數101沒問題,但是存不下22334。

如果待轉換的值與目標類型不匹配怎麼辦?這取決於轉換涉及的類型。待賦值的值與目標類型不匹配時,規則如下。

1.目標類型是無符號整型,且待賦的值是整數時,額外的位將被忽略。例如,如果目標類型是 8 位unsigned char,待賦的值是原始值求模256。

2.如果目標類型是一個有符號整型,且待賦的值是整數,結果因實現而異。

3.如果目標類型是一個整型,且待賦的值是浮點數,該行爲是未定義的。

如果把一個浮點值轉換成整數類型會怎樣?當浮點類型被降級爲整數類型時,原來的浮點值會被截斷。例如,23.12和23.99都會被截斷爲23,-23.5會被截斷爲-23。

程序清單演示了這些規則。

/************************************************************************
功能:自動類型轉換
************************************************************************/
#include <stdio.h>
int main(void)
{
	char ch;
	int i;
	float fl;
	fl = i = ch = 'C';										
	printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl);		
	ch = ch + 1;
	i = fl + 2 * ch;
	fl = 2.0 * ch + i;
	printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl);
	ch = 1107;
	printf("Now ch = %c\n", ch);
	ch = 80.89;
	printf("Now ch = %c\n", ch);
    //暫停控制檯
	system("pause");
	return 0;
}

運行後輸出如下:

ch = C, i = 67, fl = 67.00
ch = D, i = 203, fl = 339.00
Now ch = S
Now ch = P
請按任意鍵繼續. . .

在我們的系統中,char是8位,int是32位。程序的分析如下。第9行和第10行:字符'C'被作爲1字節的ASCII值儲存在ch中。整數變量i接受由'C'轉換的整數,即按4字節儲存67。最後,fl接受由67轉換的浮點數67.00。

第11行和第14行:字符變量'C'被轉換成整數67,然後加1。計算結果是4字節整數68,被截斷成1字節儲存在ch中。根據%c轉換說明打印時,68被解釋成'D'的ASCII碼。

第12行和第14行:ch的值被轉換成4字節的整數(68),然後2乘以ch。爲了和fl相加,乘積整數(136)被轉換成浮點數。計算結果(203.00f)被轉換成int類型,並儲存在i中。

第13行和第14行:ch的值('D',或68)被轉換成浮點數,然後2乘以ch。爲了做加法,i的值(203)被轉換爲浮點類型。計算結果(339.00)被儲存在fl中。

第15行和第16行:演示了類型降級的示例。把ch設置爲一個超出其類型範圍的值,忽略額外的位後,最終ch的值是字符S的ASCII碼。或者,更確切地說,ch的值是1107 % 265,即83。

第17行和第18行:演示了另一個類型降級的示例。把ch設置爲一個浮點數,發生截斷後,ch的值是字符P的ASCII碼。

強制類型轉換運算符

通常,應該避免自動類型轉換,尤其是類型降級。但是如果能小心使用,類型轉換也很方便。我們前面討論的類型轉換都是自動完成的。然而,有時需要進行精確的類型轉換,或者在程序中表明類型轉換的意圖。這種情況下要用到強制類型轉換(cast),即在某個量的前面放置用圓括號括起來的類型名,該類型名即是希望

轉換成的目標類型。圓括號和它括起來的類型名構成了強制類型轉換運算符(cast operator),其通用形式是:

(type)

用實際需要的類型(如,long)替換type即可。考慮下面兩行代碼,其中mice是int類型的變量。第2行包含兩次int強制類型轉換。 

mice = 1.6 + 1.7;
mice = (int)1.6 + (int)1.7;

第1 行使用自動類型轉換。首先,1.6和1.7相加得3.3。然後,爲了匹配int 類型的變量,3.3被類型轉換截斷爲整數3。第2行,1.6和1.7在相加之前都被轉換成整數(1),所以把1+1的和賦給變量mice。本質上,兩種類型轉換都好不到哪裏去,要考慮程序的具體情況再做取捨。

一般而言,不應該混合使用類型(因此有些語言直接不允許這樣做),但是偶爾這樣做也是有用的。C語言的原則是避免給程序員設置障礙,但是程序員必須承擔使用的風險和責任。

源碼

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