首頁 > 軟體

C語言操作符進階教學(表示式求值隱式型別轉換方法)

2022-02-16 13:01:28

結構體

結構體變數的宣告需要在主函數之上或者主函數中宣告,如果在主函數之下則會報錯,而且c語言中的結構體不能直接進行強制轉換,只有結構體指標才能進行強制轉換。

涉及結構體的操作符這裡講兩個:
. (結構體存取操作符)
-> ()

首先寫一段程式碼:

int main()
{
struct Stu s = {"me",19,60};
prinft("%s %d %lf",s.who,s.age,s.weight)
return 0;
}

這就是個結構體存取,這裡的結構是:結構體變數 . 結構體成員,箭頭怎麼用呢?當我有一個結構體指標:

struct Stu * ps = &s;
printf("%s %d %lfn"),(*ps).name,(*ps).age,(*ps).score);
return 0;

這裡我是對 ps 解除參照一下,找到他所指向的物件,其實和上面第一組程式碼的結果是一樣的;但是,橫看豎看都覺得有點囉嗦,我們把格局開啟:

printf("%s %d %lfn",ps->name,ps->age,ps->score);
return 0;

這樣是不是看著要清爽許多?->操作符的基本語法是:結構體指標 -> 結構體成員

表示式求值

我們在接觸那麼多的操作符後,就可以應用來進行計算,表示式求值的順序一部分是由操作符的優先順序和綜合性決定。同樣,有些表示式的運算元在求值過程可能需要轉換成其他型別。

隱式型別轉換

C語言的整型算術運算總是至少以預設整型型別的精度來進行的。為了獲取這個精度,表示式中的字元和短整型運算元在使用之前被轉換為普通整型,這種轉換被稱為整型提升

意義:

表示式的整型運算要在CPU的相應運算器件內執行,CPU內整型運算器(ALU)的運算元的位元組長度一般就是int的位元組長度,同時也是CPU的通用暫存器的長度。因此,即使兩個char型別的相加,在CPU執行時實際上也要先轉換為CPU內整型運算元的標準長度。通用CPU(general-purpose CPU)是難以直接實現兩個8位元位元組直接相加運算(雖然機器指令中可能有這種位元組相加指令)。所以,表示式中各種長度可能小於int長度的整型值,都必須先轉換為int或unsigned int,然後才能送入CPU去執行運算。

我們用一段程式碼代入一下:

int main()
{
char a = 5;
char b = 126;
char = a+b;
printf("%dn",c);
return 0;
}

這裡的一個表示式:a+b, 其中a和b的型別都是 char 型別,按照定義來看,也就是這段程式碼的執行遠比我們想象的複雜 ,我們知道 sizeof(char),sizeof(short)的大小肯定是小於 int 型別的,所以我們計算時就要把char,short提升成 int(unsigned int)型別,再執行運算。

方法

整型提升是按照變數的資料型別的符號位來提升的,char x = -1 中,x的二進位制位(二補數)只有8個位元位,char為有符號的char所以整型提升時,高位補充符號位,即為1;無符號整型提升,高位補0。

就拿剛剛的程式碼進行剖析:

int main()
{
char a = 5; 
//5 = 0000……0101(32位元)
//char型別一個位元組8個位元位,就只能從5的二進位制數中獲取8位元
//即a=00000101
//這一步叫截斷
char b = 126;
//126 = 0000……01111110(32位元)
//b = 01111110
char = a+b;
//當a,b相加時整型提升
//111111111……0000011
//111111111……0000010
//100000000……1111101(符號位不變,其他位按位元取反)=-125
printf("%dn",c);//
return 0;

下面這個程式碼就可以證明整型提升的存在:

int main()
{
char c= 1;
printf("%un",sizeof(c));
printf("%un",sizeof(+c));
printf("%un",sizeof(-c));
return 0;
}

從執行結果來看,為什麼會是 4 呢?其實就是因為他參與了運算,進行了整型提升,變成了int型別。

算術轉換

我們在剛剛談的是 char 和 short 的計算,那如果是int 和 long ,int 和long long,int 和 float 以及 double計算呢?他們發生的就是算術轉換。總的來說就是4位元組以下的屬於整型提升,大於4的屬於算術轉換。

是指如果其中操作符的各個運算元為不同型別,除非其中一個轉換成另一個型別,否則無法進行操作。下面層次的系統稱為尋常算術轉換

char
short
int
long
long long
float
double

short a = 10;
int b = 5;
prinft("%dn",sizeof(a+b+1));

printf 結果是 2 ,是因為short只有兩個位元組大小,在表示式中 short a 當家做主,不管放什麼進來都是short,但是,sizeof 內部多表示式其實不會真實計算,我們寫檔案通常是 test.c,要生成 .exe 的可執行檔案三步走:編譯,連結,執行。在表示式進去在編譯的時候就變成 2 了,根本到不了執行。

如果某個數型別在上表中排名較低,那會首先轉換到另一個運算元的型別後執行運算。
PS.算術轉換要合理,不然會出現潛在問題。
比如把 float 型別變成 int 型別就會造成精度丟失。

操作符屬性

複雜表示式的求值有三個影響因素:

1.操作符優先順序

2.操作符結合性

3.是否控制求值順序

首先優先順序是在求值時,相鄰兩個操作符先執行哪個的問題,當優先順序相同時,取決於他們的結合性。

什麼是結合性?舉個栗子: a = b = c;

b的左右兩側都為 = 號,而 = 具有右結合性,故應該由右向左計算,即:a = (b = c),諸如此類,有表如下(片段):

還有一些關於優先順序的常見錯誤值得注意一下:

有了上面這些屬性是不是任意給一個表示式就可以確定一個唯一的計算路徑呢?答案是:NO!比如一些問題表示式:

a*b+c*d+e*f;
a + --a;

第一個可能第一感覺就是三個部分依次先乘後加給扒拉出來,這就想的太簡單了,如果我把 abcdef 換成表示式,那就可能會相互影響,存在潛在問題。

第二個就不是計算順序的問題了,是取值時機的問題,左右運算元相互關聯時,計算路徑可能不唯一。

諸君謹記,以上程式碼誰寫誰特麼就是豬隊友,謹記!

以上就是C語言操作符進階教學(表示式求值隱式型別轉換方法)的詳細內容,更多關於C語言操作符表示式求值隱式型別轉換的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com