iT邦幫忙

0

C 語言-從放棄到入門 CH3 : 資料型態的轉換

c
  • 分享至 

  • xImage
  •  

前面的章節我們介紹了資料型態,好像每種變數一經定義就不會改變(例如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);
}

從前一章所學,a3都是整數型態,理論上運算的結果也應該是整數型態,恭喜你的直覺很準;確實我們看到c確實是被定義為int的型態,你也可以從編譯器提供的警告訊息得知這點;然而,一方面我們都知道10不能被3整除,因而預期帶有小數的結果,編譯器的推論讓我們體驗到學C的痛苦(如果沒有感覺,把這題小學數學貼到python執行一遍,保證你不想再學C了);還好我們可以透過double d = a/3;來得到帶有小數的結果,但臭蟲這時出現了!(d的值會是3.000),敏銳的讀者可能早就看出問題,因為a/3的小數再整數資料型態下已經被截斷了,因此我們需要進一步再計算前告訴編譯器,計算的結果有可能會是浮點數。

顯示轉換其中一個整數 a/(double)3 就在做這樣一件事;此時混和資料型態的計算將讓編譯器根據最佳的情況做推論,既然結果可能包含小數,則採用一個浮點數來儲存計算結果,若是計算結果可以整除,儲存為浮點數也不會失去精度。顯式轉換來完成較精確的計算;如果我們改用一個浮點數來儲存結果,就算不顯示地將兩個整數型態的計算結果轉型,C語言也會自動地進行轉換

有時顯示聲明轉換也有助於提升程式設計師對於計算結果的預期,有時則過於囉嗦 (相較於a/3.),不過大多數的情形下顯示聲明仍是利大於弊的,至少程式設計師的意圖會是明確的;關於隱式轉換的發生,基本上可以整理成以下幾種情況:

  1. 混和不同的資料型態進行運算 : 上述例子
  2. 將表達式(expression)賦予給變數 : 表達式的值向變數聲明的資料型態進行轉換
  3. 呼叫函數時 : 實際參數向形式參數所聲明的資料型態進行轉換
  4. 從函數取得回傳值 : 返回值向函數返回類型所聲明的資料型態進行轉換
    上述的例子介紹了1,讓我們介紹剩下的幾種情況。
#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 : 陣列與指標


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言