Integer Promotions in C 簡(jiǎn)介
整型提升是太深C程序設(shè)計(jì)語(yǔ)言中的一項(xiàng)規(guī)定:在表達(dá)式計(jì)算時(shí),各種整形首先要提升為int類型,整型提升如果int類型不足以表示的個(gè)隱話,就需要提升為unsigned int類型,太深然后再執(zhí)行表達(dá)式的整型提升運(yùn)算。
這一規(guī)則是個(gè)隱由C語(yǔ)言的發(fā)明人丹尼斯·里奇與肯·湯普遜創(chuàng)設(shè)的:
"A character, a short integer, or an integer bit-field, all either signed or not, or an object of enumeration type, may be used in an expression wherever an integer maybe used. If an int can represent all the values of the original type, then the value is converted to int; otherwise the value is converted to unsigned int. This process is called integral promotion."
這段話的大意是:無(wú)論使用什么整數(shù),都可以在表達(dá)式中使用char,太深short int或 int字段(全部帶符號(hào)或沒(méi)有符號(hào))或枚舉類型的整型提升對(duì)象。如果一個(gè)int可以代表原始類型的個(gè)隱所有值,則該值將轉(zhuǎn)換為int;否則,太深該值將轉(zhuǎn)換為unsigned int,這個(gè)過(guò)程稱為整體提升。
舉例子來(lái)了解一下整形提升
一些數(shù)據(jù)類型(比如char,short int)比int占用更少的字節(jié)數(shù),對(duì)它們執(zhí)行操作時(shí),這些數(shù)據(jù)類型會(huì)自動(dòng)提升為int或unsigned int,例如,在較小的類型(如char,short和enum)上不會(huì)進(jìn)行算術(shù)計(jì)算,代碼如下:
1//在win10_64位+vs2017 2#include 3int main() 4{ 5 char a = 30, b = 40, c = 10; 6 char d = (a * b) / c; 7 printf ("%d ", d); 8 system("pause"); 9 return 0; 10}
輸出結(jié)果:120
直接看代碼,表達(dá)式(a * b)/ c似乎引起算術(shù)溢出,因?yàn)閹Х?hào)的字符只能具有-128至127的值(在大多數(shù)C編譯器中),而子表達(dá)式的值(a * b)=1200,大于128。
但是整數(shù)提升是在char類型進(jìn)行算術(shù)運(yùn)算時(shí)發(fā)生的,我們得到了適當(dāng)?shù)慕Y(jié)果而沒(méi)有任何溢出。
整型提升的意義
雖然機(jī)器指令中可能有現(xiàn)兩個(gè)8比特字節(jié)這種字節(jié)相加指令,但是一般用途的CPU是難以直接實(shí)現(xiàn)這樣的字節(jié)相加運(yùn)算的。
所以,表達(dá)式中各種長(zhǎng)度可能小于int長(zhǎng)度的整型值,都必須先轉(zhuǎn)換為int或unsigned int,然后才能送入CPU去執(zhí)行運(yùn)算。
CPU內(nèi)整型運(yùn)算器(ALU)的操作數(shù)的字節(jié)長(zhǎng)度一般就是int的字節(jié)長(zhǎng)度,同時(shí)也是CPU的通用寄存器的長(zhǎng)度。而表達(dá)式的整型運(yùn)算要在CPU的相應(yīng)運(yùn)算器件內(nèi)執(zhí)行。
因此,兩個(gè)char類型的樹(shù)進(jìn)行相加運(yùn)算時(shí),是在CPU中執(zhí)行,自然而然的需要先轉(zhuǎn)換為CPU內(nèi)整型操作數(shù)的標(biāo)準(zhǔn)長(zhǎng)度。
應(yīng)用舉例
short int的長(zhǎng)度 = int的長(zhǎng)度的情況
C語(yǔ)言標(biāo)準(zhǔn)中僅規(guī)定了:
char的長(zhǎng)度 ≤ short int的長(zhǎng)度 ≤ int的長(zhǎng)度
這意味著short int與int的長(zhǎng)度相等的可能,這種情形下,unsigned short就無(wú)法提升為int表示,只能提升為unsigned int,代碼如下:
1//在win10_64位+vs2017 2#include 3int main(){ 4 char a = 0xb6; 5 short b = 0xb600; 6 int c = 0xb6000000; 7 if ( a == 0xb6) printf("a"); 8 if ( b == 0xb600) printf("b"); 9 if ( c == 0xb6000000) printf("c"); 10 system("pause"); 11}
輸出結(jié)果:c
C語(yǔ)言標(biāo)準(zhǔn)沒(méi)有規(guī)定char類型是有符號(hào)還是無(wú)符號(hào),在這些環(huán)境下,編譯器把char定義為signed char。
表達(dá)式a==0xb6被整型提升,其中char類型的a提升為int類型并表示為一個(gè)負(fù)值,因此這個(gè)表達(dá)式的結(jié)果為false;
表達(dá)式b==0xb600被整型提升,其中short類型的b提升為int類型并為一個(gè)負(fù)值,因此這個(gè)表達(dá)式的結(jié)果為false;
表達(dá)式c == 0xb6000000沒(méi)有做整型提升,==運(yùn)算符的兩段都是int類型的負(fù)值,其結(jié)果為true。
我們?cè)倏紤]以下程序作為另一個(gè)示例。
1//在win10_64位+vs2017 2#include 3 4int main() 5{ 6 char a = 0xfb; 7 unsigned char b = 0xfb; 8 9 printf("a = %c", a); 10 printf("\nb = %c", b); 11 12 if (a == b) 13 printf("\nSame"); 14 else 15 printf("\nNot Same"); 16 17 system("pause"); 18 return 0; 19}
輸出結(jié)果:
a=
b=
Not Same
當(dāng)我們打印“a”和“b”時(shí),將打印相同的字符,但是當(dāng)我們比較它們時(shí),輸出的結(jié)果卻不相同。
“a”和“b”與char具有相同的二進(jìn)制表示形式,但是,當(dāng)對(duì)“a”和 ”b”執(zhí)行比較操作時(shí),它們首先會(huì)轉(zhuǎn)換為int。
“a”是一個(gè)有符號(hào)的字符,當(dāng)轉(zhuǎn)換為int時(shí),其值變?yōu)?5(有符號(hào)的值0xfb)。
“b”是無(wú)符號(hào)字符,當(dāng)將其轉(zhuǎn)換為int時(shí),其值變?yōu)?51。
值-5和251具有不同的int表示形式,因此我們得到的輸出為“Not Same”。
前綴+的情況
C語(yǔ)言的單操作數(shù)的+運(yùn)算符(即“前綴+”),一個(gè)主要作用就是實(shí)現(xiàn)對(duì)操作數(shù)的整型提升。例如:
1//在win10_64位+vs2017 2#include 3int main() 4{ 5 char a = 1; 6 printf("%u", sizeof(a) ); 7 printf("\n"); 8 printf("%u", sizeof( +a ) ); 9 system("pause"); 10 return 0; 11}
輸出結(jié)果:
1
4
從結(jié)果中我們可以看到,前綴+把大小給提升了。
話說(shuō)C語(yǔ)言的特點(diǎn)
這里不得不提一下C語(yǔ)言的特點(diǎn),C語(yǔ)言高效、靈活、功能豐富、表達(dá)力強(qiáng),在誕生起初,為了避免各開(kāi)發(fā)廠商用的C語(yǔ)言語(yǔ)法產(chǎn)生差異,C語(yǔ)言訂定了一套語(yǔ)法ANSI C,作為C語(yǔ)言的標(biāo)準(zhǔn)。
以上所有的程序以及結(jié)論都是在win10_64位+vs2017完成的,不同平臺(tái)和不同編譯器之間可能的實(shí)驗(yàn)結(jié)果都不一樣,但這并不影響我們深入理解C語(yǔ)言的特性,講原理,摳細(xì)節(jié),究根源,樂(lè)趣在此。
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!