C語言的數據類型
c語言中,有關數據類型的分類,網上有很多種版本,未找到比較統一的標准,下圖為我比較認可的划分:

常量的默認類型
在C語言中,數值常量分為兩種:整數和小數。整數常量默認為有符號的 int 類型,而小數常量默認為 double 類型。字符常量被認為是一種特殊的整型常量,默認類型為有符號的 char ,而字符串常量一般被認為 const char 類型。需要注意的是,不同的編譯器可能略有不同,但一般遵守該規則。
隱式轉換
C語言在以下四種情況中會進行隱式轉換:
(1)算術運算式中,低類型能夠轉換為高類型。
所謂高低,是指表示的范圍大小。通常和內存默認分配的存儲空間大小及有無符號位有關。

(2)賦值表達式中,右邊表達式的值自動隱式轉換為左邊變量的類型,並賦值給它。
(3)函數調用中參數傳遞時,系統隱式地將實參轉換為形參的類型后,賦給形參。
(4)函數有返回值時,系統將隱式地將返回表達式類型轉換為返回值類型,賦值給調用函數。
算數運算中的轉換規則
算數運算中,有如下類型轉換規則:
(1)字符必須先轉換為整數(C語言規定字符類型數據和整型數據之間可以通用) 。
(2) short 型轉換為 int 型(同屬於整型) 。
(3) float 型數據在運算時一律轉換為雙精度 double 型,以提高運算精度(同屬於實型,即浮點型) 。
總的來說,當不同類型的數據進行操作時,應當首先將其轉換成相同的數據類型,然后進行操作,轉換規則是由低級向高級轉換(如上圖所示)。
算術運算示例
執行: x = 100 + 'a' + 1.5 * u + f / 'b' - s * 3.1415926
其中,u為 unsigned 型,f為 float 型,s為 short 型,x為 float 型。式中右面表達式按如下步驟處理:
- 首先將'a'、'b'和s換成 int ,將1.5和f轉換為 double 型。
- 計算100+'a',因'a'已轉換為 int 型,於是此運算結果為197。
- 計算1.5*u,由於1.5已轉換為 double ,u是 unsigned 型,於是首先u轉換為 double ,然后進行運算,運算結果為 double 。
- 計算197+1.5 * u,先將197轉換為 double (如197.00…00),其結果為 double 。
- 計算f/ 'b',f已轉換為 double ,'b'已轉換為 int ,於是先將'b'再轉換為 double ,其結果為 double 。
- 計算(197+1.5 * u)+f / 'b',者均為 double ,於是結果也為 double 。
- 計算s * 3.1415926,先將s由int轉換為 double ,然后進行運算,其結果為 double 。
- 之后與前面得的結果相減,結果為 double 。
- 最后將表達式的結果轉換為 float 並賦給x。
有符號數與無符號數之間運算問題
當表達式中存在有符號類型和無符號類型時,所有的操作數都自動轉換為無符號類型。因此,從這個意義上講,無符號數的運算優先級要高於有符號數,這一點對於應當頻繁用到無符號數據類型的嵌入式系統來說是豐常重要的。
首先進行一個實驗,分別定義一個 signed int 型數據和 unsigned int 型數據,然后進行大小比較:
unsigned int a = 20; signed int b = -130;
實驗證明:$b > a$,也就是說$-130 > 20$,為什么會出現這樣的結果呢?
這是因為在C語言操作中,如果遇到無符號數與有符號數之間的操作,編譯器會自動轉化為無符號數來進行處理,因此$a=20, b=4294967166$,這樣比較下去當然$b > a$了。再舉一個例子:
unsigned int a = 20; signed int b = -130; std::cout << a + b << std::endl;
結果輸出為$4294967186$。同樣的道理:在運算之前,$a=20$,$b$被轉化為$4294967166$,所以$a+b=42949671864,減法和乘法的運算結果類似。
如果作為 signed int 型數據的b=-130,b與立即數之間操作時不影響b的類型,運算結果仍然為 signed int 型:
signed int b = -130; std::cout << b + 30 << std::endl; // 輸出為-100
而對於浮點數來說,浮點數 float, double 實際上都是有符號數, unsigned 和 signed 前綴不能加在 float 和 double 之上,當然就不存在有符號數根無符號數之間轉化的問題了。
示例
#include <iostream> /* 當表達式中存在符號類型和無符號類型時 所有的操作數都自動轉換為無符號類型 */ using namespace std; char getChar(int x,int y){ char c; unsigned int a = x; unsigned int b = a + y; (a + y > 10)?(c = 1):(c = 2); return c; } void main(){ char c1 = getChar(7,4); char c2 = getChar(7,3); char c3 = getChar(7,-7); char c4 = getChar(7,-8); printf("c1=%d\n",c1); printf("c2=%d\n",c2); printf("c3=%d\n",c3); printf("c4=%d\n",c4); system("pause"); } // 輸出: c1=1 c2=2 c3=2 c4=1
規則總結
范例解析
unsigned int i = 3; cout << i * -1; // 輸出?
各數據類型的表示范圍
來自MSDN

補充說明:
答案
(整理自網絡)
參考資料:
https://blog.csdn.net/zhuimengzh/article/details/6728492
https://blog.csdn.net/miaouu/article/details/5213042
