1. 程式人生 > >c/c++程式設計排坑(1)-- 資料型別的“安靜”轉換

c/c++程式設計排坑(1)-- 資料型別的“安靜”轉換

這裡主要介紹ANSI C的特性:當執行算術運算時,運算元的型別如果不同,就會發生轉換。資料型別一般朝著精度更高、長度更長的方向轉換,整型數如果轉換為signed不會丟失資訊,就轉換為signed,否則轉換為unsigned。

一、算術轉換(K&R C)

首先:

  • 任何型別為char或short的運算元會被轉換為int。
  • 任何型別為float的運算元會被轉換成double。

其次:

  • 如果其中一個運算元的型別時double,那麼另外一個運算元會被轉換成double,計算結果也是double。
  • 如果其中一個運算元的型別時long,那麼另外一個運算元會被轉換成long,計算結果也是long。
  • 如果其中一個運算元的型別時unsigned,那麼另外一個運算元會被轉換成unsigned,計算結果也是unsigned。

如果不符合上面幾種情況,那麼兩個運算元的型別都作為int,計算結果也是int。

二、ANSI C的做法

字元和整型(整型升級)

char,short int或者int型位段(bit-field),包括他們的有符號和無符號變型,以及列舉型別,可以使用在需要int或unsigned int的表示式中。如果int可以完整表示源型別的所有值,那麼該源型別的值就轉換為int,否則轉換為unsigned int。這稱之為整型升級。

尋常算術轉換

許多運算元型別為算數型別的雙目運算子會引發型別轉換,並以類似的方式產生結果型別。它的目的是產生一個普通型別,同時也是運算結果的型別。這個模式稱之為尋常算術轉換。

具體解釋起來較為費篇幅,簡單而言(不嚴謹的說)就是開篇提到的那段話:

當執行算術運算時,運算元的型別如果不同,就會發生轉換。資料型別一般朝著精度更高、長度更長的方向轉換,整型數如果轉換為signed不會丟失資訊,就轉換為signed,否則轉換為unsigned。

一個型別轉換bug

往往我們對算術轉換都相對敏感,比如float轉double之類。而對有符號無符號則相對沒那麼注意。接下來舉個例子,請先看程式碼,猜猜輸出是什麼?

#include <iostream>
#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))
using namespace std;
int array[] = {1,2,3,4,5,6,7,8,9};
int main()
{
    int d = -1;
    if(d < TOTAL_ELEMENTS)
        cout << "-1 小於 TOTAL_ELEMENTS" << endl;
    else
        cout << "-1 大於 TOTAL_ELEMENTS" << endl;
}

輸出是:
TOTAL_ELEMENTS = 9
-1 大於 TOTAL_ELEMENTS

你答對了嗎?
結論竟然是:-1<9。這是因為if在signed int和unsigned之間測試相等性,d被升級為unsigned int型別,-1被轉換成unsigned int將是一個非常大的數!!!

See you next time. Happy Coding!!!
我的github