??博客主頁: 小羊失眠啦.
??系列專欄: C語言
???每日語錄:但行前路,不負韶華!
??感謝大家點贊??收藏?評論??
前言
今天小羊又來給鐵汁們分享關(guān)于C語言的隱式類型轉(zhuǎn)換規(guī)則
,在C語言中類型轉(zhuǎn)換方式可分為隱式類型轉(zhuǎn)換
和顯式類型轉(zhuǎn)換
(強制類型轉(zhuǎn)換),其中隱式類型轉(zhuǎn)換是由編譯器自動進行,無需程序員干預(yù),今天小羊課堂說的就是關(guān)于隱式類型轉(zhuǎn)換,隱式類型轉(zhuǎn)換分為兩種情況:整型提升和算術(shù)轉(zhuǎn)換
。
一、隱式類型轉(zhuǎn)換的規(guī)則
在c語言中,自動類型轉(zhuǎn)換遵循以下規(guī)則:
- 若參與運算量的類型不同,則先轉(zhuǎn)換成同一類型,然后進行運算。
- 轉(zhuǎn)換按數(shù)據(jù)長度增加的方向進行,以保證精度不降低。如int型和long型運算時,先把int量轉(zhuǎn)成long型后再進行運算。
a、若兩種類型的字節(jié)數(shù)不同,轉(zhuǎn)換成字節(jié)數(shù)高的類型
b、若兩種類型的字節(jié)數(shù)相同,且一種有符號,一種無符號,則轉(zhuǎn)換成無符號類型 - 所有的浮點運算都是以雙精度進行的,即使僅含float單精度量運算的表達式,也要先轉(zhuǎn)換成double型,再作運算。
- char型和short型參與運算時,必須先轉(zhuǎn)換成int型。
- 在賦值運算中,賦值號兩邊量的數(shù)據(jù)類型不同時,賦值號右邊量的類型將轉(zhuǎn)換為左邊量的類型。如果右邊量的數(shù)據(jù)類型長度比左邊長時,將丟失一部分數(shù)據(jù),這樣會降低精度,丟失的部分按四舍五入向前舍入。
二、整型提升
C的整型算術(shù)運算總是至少以缺省整型類型的精度來進行的,為了獲得這個精度,表達式中的字符和短整型操作數(shù)在使用之前被轉(zhuǎn)換為普通整型,這種轉(zhuǎn)換稱為整型提升。
原理
有符號補符號位,無符號位無腦補0
1.負數(shù)的整型提升
高位補充符號位,即補1
char a=-1;
變量a的二進制位(補碼)中只有8個比特位:
11111111
因為char是有符號的char
所以整型提升的時候,補符號位,即補1
提升結(jié)果:
11111111 11111111 11111111 11111111
2.正數(shù)的整型提升
高位補充符號位,即補0
char a=1;
變量a的二進制位(補碼)中只有8個比特位:
00000001
因為char是無符號的char
所以整型提升的時候,補符號位,即補0
提升結(jié)果:
00000000 00000000 00000000 00000001
3.無符號的整型提升
無符號整型提升,高位補0(無符號只有正數(shù))
三、整型提升實例
例1:
#include <stdio.h>
int main()
{
char a = 5, b = 127;
char c = a + b;
int d = a + b;
printf("c=%d\n", c);
printf("d= %d", d);
return 0;
}
運行結(jié)果:
c=-124
d=132
分析:
char a=5
0000 0101 --> a=5
char b=127
0111 1111 --> b=127
因為參與了運算,并且char類型的精度小于int類型,所以這里進行整型提升:
00000000 00000000 00000000 00000101 --> a=5
00000000 00000000 00000000 01111111 --> b=127
00000000 00000000 00000000 10000100 --> c=132
//1:>
將結(jié)果存入類型為char的變量c中,c只能存儲8位,所以保留結(jié)果最后8位
1000 0100 --> c=132
由于char類型也是有正負的,且計算結(jié)果是以補碼形式,轉(zhuǎn)化為原碼
補碼:1000 0100
反碼:1000 0011
原碼:1111 1100 --> -124
原碼值為-124
//2:>
運算還是先整型提升再運算,二進制同上,最后結(jié)果存放到int類型的b中,所以直接就是132
例2:
#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
分析:
a=0xb6
整型提升前:10110110
整型提升后:11111111 11111111 11111111 10110110 可以直接看出這是一個負數(shù)的補碼
b=0xb600
整型提升前:10110110 00000000
整型提升后:11111111 11111111 10110110 00000000 可以直接看出這也是一個負數(shù)的補碼
c=0xb6000000
無需整型提升,故結(jié)果為真
例3:
#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;
}
運行結(jié)果:
c=1
c=4
c=4
分析:
sizeof(c),c沒有參與運算,故就是求char類型大小
sizeof(+c),sizeof(-c),c參與運算,整型提升為int,故就是求int類型大小
四、算術(shù)轉(zhuǎn)移
如果某個操作符的各個操作數(shù)屬于不同的類型,那么除非其中一個操作數(shù)轉(zhuǎn)換為另一個操作數(shù)的類型,否則操作就無法進行,下面的尋常算術(shù)轉(zhuǎn)換。
//從高到低
long double
double
float
unsigned long int
long int
unsigned int
int
注:
如果在同一運算中操作數(shù)類型不同,等級低的要往等級高的轉(zhuǎn)換。
算術(shù)轉(zhuǎn)換要合理,否則會存在潛在的問題
例1:
float f=3.14;
int num=f;//隱式轉(zhuǎn)換,精度丟失
例2:
#include<stdio.h>
int main()
{
unsigned char a = 0;
unsigned char b = 255;
unsigned char c = 255;
a = b + c;
printf("a = %d\n", a);
return 0;
}
運行結(jié)果:
a = 254
分析:
b和c的值都需要提升為整型,再執(zhí)行加法運算
b\c:>
整型提升前:11111111
整型提升后:11111111 11111111 11111111 11111111
11111111 11111111 11111111 11111111 --> b
11111111 11111111 11111111 11111111 --> c
111111111 11111111 11111111 11111110 --> a
結(jié)果保留最后的8位
11111110 --> 補碼
由于是無符號char類型,那么原反補一樣
原碼也是11111110 即為254
總結(jié)
發(fā)生轉(zhuǎn)換的原因:
硬件:CPU寄存器的比特位是統(tǒng)一的,將內(nèi)存中的數(shù)據(jù)放入寄存器中就會發(fā)生隱式轉(zhuǎn)換
軟件:C語言的操作符對多個操作數(shù)進行操作時,必須保證其類型一致
五、操作符的屬性
1.操作符
復(fù)雜表達式的求值有三個影響的因素。
-
操作符的優(yōu)先級
。決定了有多個操作符和多個操作數(shù)時,先執(zhí)行哪部分。 -
操作符的結(jié)合性
。當優(yōu)先級相同,多個或單個操作符之間從左向右執(zhí)行還是從右向左執(zhí)行。 -
是否控制求值順序
。特定的某些表達式在進行求值,根據(jù)不同的條件產(chǎn)出不同的求值過程。
兩個相鄰的操作符先執(zhí)行哪個?取決于他們的優(yōu)先級。如果兩者的優(yōu)先級相同,取決于他們的結(jié)合性。
2.操作符優(yōu)先級
操作符優(yōu)先級,從上往下,重點的
操作符 | 結(jié)合性 | 是否控制求值順序 |
---|---|---|
() | N/A | 否 |
, | L-R | 否 |
-> | L-R | 否 |
++ | L-R | 否 |
– | L-R | 否 |
++ | R-L | 否 |
– | R-L | 否 |
* | R-L | 否 |
3.問題表達式
表達式1
a*b + c*d + e*f
注釋:代碼1在計算的時候,由于乘法的優(yōu)先級比+的優(yōu)先級高,只能保證的乘法計算是比+早,但是優(yōu)先級并不能決定第三個*比第一個+早執(zhí)行。
所以表達式的計算機順序就可能是:
a*b
c*d
a*b + c*d
e*f
a*b + c*d + e*f
或者:
a*b
c*d
e*f
a*b + c*d
a*b + c*d + e*f
表達式2
非法表達式1
int main()
{
int i = 10;
i = i-- - --i * (i = -3) * i++ + ++i;
printf("i = %d\n", i);
return 0;
}
非法表達式2
int fun()
{
static int count = 1;
return ++count; }
int main()
{
int answer;
answer = fun() - fun() * fun();
printf( "%d\n", answer);//輸出多少?
return 0; }
這兩個表達式,鐵汁們要好好思考這為什么是非法的,不懂得可以私信小羊哦
總結(jié):
我們寫出的表達式如果不能通過操作符的屬性確定唯一的計算路徑,那這個表達式一定存在問題
好了,今天小羊分享的C語言的隱式類型轉(zhuǎn)換規(guī)則就講到這里了,歡迎大家評論區(qū)留言~~文章來源:http://www.zghlxwxcb.cn/news/detail-647284.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-647284.html
到了這里,關(guān)于『C語言初階』第八章 -隱式類型轉(zhuǎn)換規(guī)則的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!