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