前面的章節我們介紹了資料型態,好像每種變數一經定義就不會改變(例如int var;
,往後var
只能是整數),然而當不同型態的變數互相作用(包含變數間的計算、呼叫函數的形式參數與實值參數等)時,資料的型態需要有所轉變是完全可預期的需求;而這方面C語言也提供了相應的轉換機制,因此,我們大可區分資料型態的轉換為顯示(explicitly)、隱式(implicitly)的轉換,顧名思義,顯示轉換是我們直接用語法顯示的定義要轉換的目標資料型態,反之,隱式的資料型態轉換則是在某些情況下自動產生的,讓我們看一個範例吧 ~
首先是顯示的型態轉換,語法上很簡單,用括弧包夾要轉換的型別即可,例如int tmp = (int)3.4;
將整數浮點數常量(literal)3.4
轉換為整數,再賦值給整數變數tmp
;反之,我們採用auto
關鍵字展示編譯器做的隱式判斷。
#include<stdio.h>
int main(){
int a = 10;
auto b = a/3;
auto d = a/(double)3;
printf("auto inference : %d\n", b);
printf("get precise result : %f", d);
}
從前一章所學,a
和3
都是整數型態,理論上運算的結果也應該是整數型態,恭喜你的直覺很準;確實我們看到c
確實是被定義為int
的型態,你也可以從編譯器提供的警告訊息得知這點;然而,一方面我們都知道10
不能被3
整除,因而預期帶有小數的結果,編譯器的推論讓我們體驗到學C的痛苦(如果沒有感覺,把這題小學數學貼到python執行一遍,保證你不想再學C了);還好我們可以透過double d = a/3;
來得到帶有小數的結果,但臭蟲這時出現了!(d
的值會是3.000
),敏銳的讀者可能早就看出問題,因為a/3
的小數再整數資料型態下已經被截斷了,因此我們需要進一步再計算前告訴編譯器,計算的結果有可能會是浮點數。
顯示轉換其中一個整數 a/(double)3
就在做這樣一件事;此時混和資料型態的計算將讓編譯器根據最佳的情況做推論,既然結果可能包含小數,則採用一個浮點數來儲存計算結果,若是計算結果可以整除,儲存為浮點數也不會失去精度。顯式轉換來完成較精確的計算;如果我們改用一個浮點數來儲存結果,就算不顯示地將兩個整數型態的計算結果轉型,C語言也會自動地進行轉換。
有時顯示聲明轉換也有助於提升程式設計師對於計算結果的預期,有時則過於囉嗦 (相較於
a/3.
),不過大多數的情形下顯示聲明仍是利大於弊的,至少程式設計師的意圖會是明確的;關於隱式轉換的發生,基本上可以整理成以下幾種情況:
#include<stdio.h>
void print_char(char c){ printf("convert to char '%c'\n", c); }
double return_doub(){ return 3.14; }
int main(){
/**********************************************************
case 2. 簡單的 expression : a/3 賦予變數 b
**********************************************************/
int a = 10, b = a/3; // 單行定義兩變數,等同於分開定義 int a=10; int b=a/3;
printf("int result : %d\n", b);
/***********************************************************
case 3. 呼叫函數 : 整數的實際參數 65 向字元的形式參數轉換
************************************************************/
print_char(65);
// 函數回傳值原本為浮點數
printf("convert to float '%f'\n", return_doub(3.14));
/*********************************************************************
case 4. 接收函數回傳值 : 浮點數的回傳值3.14向變數聲明的資料型態進行轉換
*********************************************************************/
int cut_doub = return_doub(3.14);
printf("cutted double : %d", cut_doub);
return 0;
}
在第2個case中,a/3
作為一個表達式向整數變數b
賦值,因此運算結果會被轉為整數型態。
第3個case中,整數常量65
作為實際參數向print_char
聲明的形式參數字元進行轉換。
第4個case中,與將表達式賦予給變數類似,同樣藉由聲明接收回傳值的變數來決定其資料型態的轉換。
程式執行結果
!gcc -o les2_tst.exe lesson2_test.c ; ./les2_tst.exe
>> int result : 3
convert to char 'A'
convert to float '3.140000'
cutted double : 3
預告 CH4 : 陣列與指標