C語言中你不知道的隱式類型轉(zhuǎn)換規(guī)則詳解
前言
- 在 C 語言中,類型轉(zhuǎn)換的方式一般可分為隱式類型轉(zhuǎn)換和顯示類型轉(zhuǎn)換(也稱為強(qiáng)制類型轉(zhuǎn)換)。
- 其中隱式類型轉(zhuǎn)換由編譯器自動進(jìn)行,不需要程序員干預(yù)。
- 隱式類型轉(zhuǎn)換通常有兩種情況:整形提升和算術(shù)轉(zhuǎn)換。
一、隱式類型轉(zhuǎn)換的規(guī)則
在C語言中,自動類型轉(zhuǎn)換遵循以下規(guī)則:
- 若參與運(yùn)算量的類型不同,則先轉(zhuǎn)換成同一類型,然后進(jìn)行運(yùn)算。
- 轉(zhuǎn)換按數(shù)據(jù)長度增加的方向進(jìn)行,以保證精度不降低。如int型和long型運(yùn)算時,先把int量轉(zhuǎn)成long型后再進(jìn)行運(yùn)算。
a、若兩種類型的字節(jié)數(shù)不同,轉(zhuǎn)換成字節(jié)數(shù)高的類型
b、若兩種類型的字節(jié)數(shù)相同,且一種有符號,一種無符號,則轉(zhuǎn)換成無符號類型 - 所有的浮點運(yùn)算都是以雙精度進(jìn)行的,即使僅含float單精度量運(yùn)算的表達(dá)式,也要先轉(zhuǎn)換成double型,再作運(yùn)算。
- char型和short型參與運(yùn)算時,必須先轉(zhuǎn)換成int型。
- 在賦值運(yùn)算中,賦值號兩邊量的數(shù)據(jù)類型不同時,賦值號右邊量的類型將轉(zhuǎn)換為左邊量的類型。如果右邊量的數(shù)據(jù)類型長度比左邊長時,將丟失一部分?jǐn)?shù)據(jù),這樣會降低精度,丟失的部分按四舍五入向前舍入。
二、整型提升
C的整型算術(shù)運(yùn)算總是至少以缺省整型類型的精度來進(jìn)行的。
為了獲得這個精度,表達(dá)式中的字符和短整型操作數(shù)在使用之前被轉(zhuǎn)換為普通整型,這種轉(zhuǎn)換稱為整型提升。
1.整型提升的意義
表達(dá)式的整型運(yùn)算要在CPU的相應(yīng)運(yùn)算器件內(nèi)執(zhí)行,CPU內(nèi)整型運(yùn)算器(ALU)的操作數(shù)的字節(jié)長度。
一般就是int的字節(jié)長度,同時也是CPU的通用寄存器的長度。
因此,即使兩個char類型的相加,在CPU執(zhí)行時實際上也要先轉(zhuǎn)換為CPU內(nèi)整型操作數(shù)的標(biāo)準(zhǔn)長度。
通用CPU(general-purpose CPU)是難以直接實現(xiàn)兩個8比特字節(jié)直接相加運(yùn)算(雖然機(jī)器指令中可能有這種字節(jié)相加指令)。所以,表達(dá)式中各種長度可能小于int長度的整型值,都必須先轉(zhuǎn)換為int或unsigned int,然后才能送入CPU去執(zhí)行運(yùn)算。
代碼示例:
char a,b,c; a = b + c;
b和c的值被提升為普通整型,然后再執(zhí)行加法運(yùn)算。
加法運(yùn)算完成之后,結(jié)果將被截斷,然后再存儲于a中。
2.如何進(jìn)行整體提升?
整形提升是按照變量的數(shù)據(jù)類型的符號位來提升的
2.1正數(shù)的整形提升
高位補(bǔ)充符號位,即補(bǔ)0
char c2 = 1; 變量c2的二進(jìn)制位(補(bǔ)碼)中只有8個比特位: 00000001 因為 char 為有符號的 char //VS中默認(rèn)char為有符號char 所以整形提升的時候,高位補(bǔ)充符號位,即為0 提升之后的結(jié)果是: 00000000000000000000000000000001
2.2負(fù)數(shù)的整型提升
高位補(bǔ)充符號位,即補(bǔ)1
char c1 = -1; 變量c1的二進(jìn)制位(補(bǔ)碼)中只有8個比特位: 1111111 因為 char 為有符號的 char 所以整形提升的時候,高位補(bǔ)充符號位,即為1 提升之后的結(jié)果是: 11111111111111111111111111111111
2.3無符號整型提升
高位補(bǔ)0
3.整型提升實例
代碼示例1:
#include<stdio.h> int main() { char a = 0xb6; short b = 0xb600; int c = 0xb6000000; if (a == 0xb6) printf("a"); if (b == 0xb600) printf("b"); if (c == 0xb6000000) printf("c"); return 0; }
代碼結(jié)果:
c
結(jié)果分析:
實例1中的a,b要進(jìn)行整形提升,但是c不需要整形提升
a,b整形提升之后,變成了負(fù)數(shù),所以表達(dá)式 a0xb6 , b0xb600的結(jié)果是假,但是c不發(fā)生整形提升,則表達(dá)式 c==0xb6000000 的結(jié)果是真.
代碼示例2:
#include<stdio.h> int main() { char c = 1; printf("c=%u\n", sizeof(c));//%u按無符號整形unsigned int打印 printf("c=%u\n", sizeof(+c)); printf("c=%u\n", sizeof(-c)); return 0; }
c=1
c=4
c=4
實例2中的,c只要參與表達(dá)式運(yùn)算,就會發(fā)生整形提升,表達(dá)式 +c ,就會發(fā)生提升,所以 sizeof(+c) 是4個字節(jié)。
表達(dá)式 -c 也會發(fā)生整形提升,所以 sizeof(-c) 是4個字節(jié),但是 sizeof© ,就是1個字節(jié)。
三、算術(shù)轉(zhuǎn)換
如果某個操作符的各個操作數(shù)屬于不同的類型,那么除非其中一個操作數(shù)的轉(zhuǎn)換為另一個操作數(shù)的類型,否則操作就無法進(jìn)行。下面的層次體系稱為尋常算術(shù)轉(zhuǎn)換。
//排名由高到低 long double double float unsigned long int long int unsigned int int
如果某個操作數(shù)的類型在上面這個列表中排名較低,那么首先要轉(zhuǎn)換為另外一個操作數(shù)的類型后執(zhí)行運(yùn)算。
警告:
但是算術(shù)轉(zhuǎn)換要合理,要不然會有一些潛在的問題。
代碼示例:
如果某個操作數(shù)的類型在上面這個列表中排名較低,那么首先要轉(zhuǎn)換為另外一個操作數(shù)的類型后執(zhí)行運(yùn)算。
警告:
但是算術(shù)轉(zhuǎn)換要合理,要不然會有一些潛在的問題。
代碼示例:
#include<stdio.h> int main() { float f = 3.14; int num = f;//隱式轉(zhuǎn)換,會有精度丟失 printf("num=%d",num); }
代碼結(jié)果:
num=3
結(jié)果分析:
在賦值運(yùn)算過程中,當(dāng)兩邊的數(shù)據(jù)類型不一樣時,右邊的數(shù)據(jù)將強(qiáng)制轉(zhuǎn)換為左邊的數(shù)據(jù),即float類型的b將強(qiáng)制轉(zhuǎn)會為int類型,小數(shù)點后面的部分直接丟棄,導(dǎo)致精度下降。
小結(jié)
以上就是C語言中你不知道的隱式類型轉(zhuǎn)換規(guī)則詳解的詳細(xì)內(nèi)容,更多關(guān)于C語言隱式類型轉(zhuǎn)換規(guī)則的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C/C++自主分配出現(xiàn)double free or corruption問題解決
這篇文章主要為大家介紹了C/C++出現(xiàn)double free or corruption問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04