這裡主要介紹ANSI C的特性:當執行算術運算時,操作數的類型如果不同,就會發生轉換。數據類型一般朝著精度更高、長度更長的方向轉換,整型數如果轉換為signed不會丟失信息,就轉換為signed,否則轉換為unsigned。 一、算術轉換(K&R C) 首先: 任何類型為char或short的操作數 ...
這裡主要介紹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