C語言之優先順序 結合性與自增運算

2021-07-16 22:11:54 字數 2674 閱讀 6052

優先順序、結合性這些概念在初學的時候並沒有放在心上,今天又碰到這個問題,查了不少資料,再次做個總結。

在標準c語言的文件裡,對操作符的結合性並沒有做出非常清楚的解釋。乙個滿分的回答是:它是仲裁者,在幾個操作符具有相同的優先順序時決定先執行哪乙個。

每個操作符擁有某一級別的優先順序,同時也擁有左結合性或右結合性。優先順序決定乙個不含括號的表示式中運算元之間的「緊密」程度。例如,在表示式a*b+c中,乘法運算的優先順序高於加法運算子的優先順序,所以先執行乘法a*b,而不是加法b+c。

但是,許多操作符的優先順序都是相同的。這時,操作符的結合性就開始發揮作用了。在表示式中如果有幾個優先順序相同的操作符,結合性就起仲裁的作用,由它決定哪個操作符先執行。像下面這個表示式:

int a,b=1,c=2;

a=b=c;

我們發現,這個表示式只有賦值符,這樣優先順序就無法幫助我們決定哪個操作先執行,是先執行b=c呢?還是先執行a=b。如果按前者,a=結果為2,如果按後者,a的結果為1。

所有的賦值符(包括復合賦值)都具有右結合性,就是在表示式中最右邊的操作最先執行,然後從右到左依次執行。這樣,c先賦值給b,然後b在賦值給a,最終a的值是2。類似地,具有左結合性的操作符(如位操作符「&」和「|」)則是從左至右依次執行。

結合性只用於表示式中出現兩個以上相同優先順序的操作符的情況,用於消除歧義。事實上你會注意到所有優先順序相同的操作符,它們的結合性也相同。這是必須如此的,否則結合性依然無法消除歧義,如果在計算表示式的值時需要考慮結合性,那麼最好把這個表示式一分為二或者使用括號。 例:

a=b+c+d

=是右結合的,所以先計算(b+c+d),然後再賦值給a

+是左結合的,所以先計算(b+c),然後再計算(b+c)+d

c語言中具有右結合性的運算子包括所有單目運算子以及賦值運算子(=)和條件運算子。其它都是左結合性。

在c語言中有少數運算子在c語言標準中是有規定表示式求值的順序的:

1:&& 和 || 規定從左到右求值,並且在能確定整個表示式的值的時候就會停止,也就是常說的短路。

2:條件表示式的求值順序是這樣規定的:

test ? exp1 : exp2;

條件測試部分test非零,表示式exp1被求值,否則表示式exp2被求值,並且保證exp1和exp2兩者之中只有乙個被求值。

3:逗號運算子的求值順序是從左到右順序求值,並且整個表示式的值等於最後乙個表示式的值,注意逗號','還可以作為函式引數的分隔符,變數定義的分隔符等,這時候表示式的求值順序是沒有規定的!

判斷表示式計算順序時,先按優先順序高的先計算,優先順序低的後計算,當優先順序相同時再按結合性,或從左至右順序計算,或從右至左順序計算。

說完了優先順序和結合性,下面說說自增運算子++ 

首先明白自增運算子的兩種使用情況:

(1)、單獨使用:i++;或者++1;這種情況下兩者是沒有區別的,i的值都會增加1;

(2)、在表示式中使用:a = i++;此時先取i的值賦給a,然後i的值自增,相當於a = i;i=i+1

a = ++i;此時先讓i自增,然後將自增後的值賦給a,相當於i = i + 1;a = i

明白了自增的這兩種情況,然後再來看看自增和結合性的混合情況:*p++ (*p)++ *(p++)三者的區別

對於*p++,首先*和++的優先順序相同,然後看他們的結合性;由於優先順序相同,那麼他們的結合性必然也相同,都是右結合(從右至左)。

那麼*p++ 就相當於*(p++),即根據右結合,p與++先結合形成(p++),然後再與*結合。

需要注意的一點(本文想著重說明的一點):

雖然*(p++)中,p++被放在了括號內,此時應根據自增運算子++的兩種情況來考慮(而不需要考慮結合性了,此時與結合性已經無關),顯然這是上述的第二種情況,即在表示式中使用自增。所以是先取p的值與*結合,然後p值再自增,相當於*p,p++;千萬不要被括號迷惑,認為括號中的東西先運算。

明白了上面一點,則對於*(++p)就很好理解,p先自增,然後與*結合。

對於下面的例子也不難理解:
例一:

char q[5] = "am";

char *p = q;char q[5] = "am";

char *p = q;

那麼,

(1)(*p)++後,p就變成了"bm";因為是進行對其首元素進行加1運算

*(p++)後,p就變成了"m",因為完成取值運算後,p++指向下乙個元素,即m,

*p++與*(p++)一樣。

(2)如果只是針對這3個語句賦值給其他變數的話,3個的結果都是a,在這裡:

char o = (*p)++;

char m = *(p++);

char n = *p++;

都是a。

例二:

int i = 0,a,b;

a = (i++)+(i++)+(i++);

b = (++i)+(++i)+(++i);

cout《輸出結果(gcc編譯器):0 16 6

解釋:這裡特別註明是gcc編譯器,在其他編譯器下的值可能不同。

對於int a=(i++)+(i++)+(i++);先取出i值進行加運算,然後再執行i的三次自增; 在其他編譯器下(如tc3.0),可能是0+1+2=3;

對於int b=(++i)+(++i)+(++i);每次i先自增,然後參與運算,所以是4+5+6=16.

運算的優先順序與結合性

運算子型別 優先順序運算子 運算物件的個數 結合性 基本 1 自左至右單目 2 type sizeof 1 單目運算子 自右至左算術 3 2 雙目運算子 自左至右 4 移位 5 2 雙目運算子 自左至右關係 6 2 雙目運算子 自左至右 7 位邏輯8 2 雙目運算子 自左至右 9 10 邏輯 11 ...

C語言運算子的優先順序與結合性

概括 一般的想法是掌握優先順序與結合性意義不大,因為可以用括號搞定一切,但是我們不能保證別人也這麼做,所以在看別人的程式時,就有可能因為優先順序和結合性的問題而理解錯誤。總結一些規律來記住優先順序和結合性是有必要的。一 優先順序由高到底順序如下 規律一 運算子所需要的運算元越多優先順序越低。1 特殊...

C語言運算子優先順序及結合性

今天去翻了下c語言運算子的優先順序和結合性,發現當初學習的時候就沒認真記住,慚愧。發現一篇講得不錯的文章,編輯了下轉來供以後翻閱。c語言運算子優先順序表 由上至下,優先順序依次遞減 運算子 結合性 自左向右 type sizeof 自右向左 自左向右 自左向右 自左向右 自左向右 自左向右 自左向右...