1. 程式人生 > >C語言中++自增運算子後置時的使用說明(附C語言運算子優先順序表)

C語言中++自增運算子後置時的使用說明(附C語言運算子優先順序表)

首先吐槽一聲:後置++運算子就是個坑!!

有學弟問我一道C語言題目,如下:

int x = 11,則表示式(x++*1/3)的值是多少?

對答案這個先賣個關子,學弟老實明白的告訴我:答案不重要,就是感覺很糾結。

我很認真的思考,仔細的分析,然後用VS測試了一下,於是我也開始糾結了。

按照++優先順序高於*與/,而++是自增,那顯然答案應該是4啊!當然不出您的預料(或者大牛已經在偷笑),明明就是3!!!

這究竟是為什麼呢?我開始尋找答案。在C++ Primer裡面有提到++使用說明,按我的理解翻譯過來即:後置形式的自增自減(形如x++, x--),先儲存運算元原來的數值,然後對運算元進行自增自減操作,然後返回之前儲存的運算元的值即未進行自增自減操作的值。或者通俗來說即:先使用x的值進行運算,最後再自+1(還是++x這樣好用,直接先自+1再做其他運算唄)。

這樣一來就比較明顯了,不過還是再用幾個簡單的例子來驗證一下這個結論。

double x = 11, y = 11;
printf("%f\n", x++/3);
double m = y++ / 3;
printf("%f, %f\n", y, m);
return 0;

如上,先計算x/3, 輸出3.666667,此時x自+1,則x = 12。對於y來說同樣道理為12,對於m則是相當於做自+1運算前x的情形,為3.666667。也就是說,++作為不管前置還是後置運算時,都是對運算值進行操作的,這點一定要想清楚。

double x = 11, y = 11;
//printf("%f\n", x++/3);
y = y++ / 3;
printf("%f\n", y);
return 0;

若如此這般呢?

y首先作為double除以3,得到3.666667,然後賦值給了等號左邊的y,最後進行自+1,即得4.666667這樣的一個結果!

本來想在譚浩強老師的書裡找一下相關解釋,最終未能成功(不知道附錄裡面提到的:結合方向,自右向左能否勉強算是)。

那麼總結一下,後置使用++自增運算子就是坑!(弱弱吐槽一句本科C課程居然考這種能避則避的坑的情形),若要用到自增運算子(鑑於它的方便起見,還是應該儘量多用),用前置的,比如++i這種就好啦,方便,省心。(縱觀譚老師的書,滿篇的i++,實在與C++ Primer中“建議:只有在必要時才使用後置操作符”、“養成使用前置操作符這個好習慣”,格格不入啊)

另外還需注意,C++ Primer裡面還有提到:對於int型物件和指標,編譯器可優化點這項額外工作,但是對於更多的複雜迭代器 型別,這種額外工作可能會花費更大的代價。即是說,對於int型物件和指標,編譯器進行了優化,直接把x的值賦給了表示式左邊的值,然後對x進行自增。【1】

附錄 C語言運算子優先順序詳細列表【2】

優先順序

運算子

名稱或含義

使用形式

結合方向

說明

1

[]

陣列下標

陣列名[常量表達式]

左到右

()

圓括號

(表示式)/函式名(形參表)

.

成員選擇(物件)

物件.成員名

->

成員選擇(指標)

物件指標->成員名

2

-

負號運算子

-表示式

右到左

單目運算子

(型別)

強制型別轉換

(資料型別)表示式

++

自增運算子

++變數名/變數名++

單目運算子

--

自減運算子

--變數名/變數名--

單目運算子

*

取值運算子

*指標變數

單目運算子

&

取地址運算子

&變數名

單目運算子

!

邏輯非運算子

!表示式

單目運算子

~

按位取反運算子

~表示式

單目運算子

sizeof

長度運算子

sizeof(表示式)

3

/

表示式/表示式

左到右

雙目運算子

*

表示式*表示式

雙目運算子

%

餘數(取模)

整型表示式/整型表示式

雙目運算子

4

+

表示式+表示式

左到右

雙目運算子

-

表示式-表示式

雙目運算子

5

<<

左移

變數<<表示式

左到右

雙目運算子

>>

右移

變數>>表示式

雙目運算子

6

>

大於

表示式>表示式

左到右

雙目運算子

>=

大於等於

表示式>=表示式

雙目運算子

<

小於

表示式<表示式

雙目運算子

<=

小於等於

表示式<=表示式

雙目運算子

7

==

等於

表示式==表示式

左到右

雙目運算子

!=

不等於

表示式!= 表示式

雙目運算子

8

&

按位與

表示式&表示式

左到右

雙目運算子

9

^

按位異或

表示式^表示式

左到右

雙目運算子

10

|

按位或

表示式|表示式

左到右

雙目運算子

11

&&

邏輯與

表示式&&表示式

左到右

雙目運算子

12

||

邏輯或

表示式||表示式

左到右

雙目運算子

13

?:

條件運算子

表示式1? 表示式2: 表示式3

右到左

三目運算子

14

=

賦值運算子

變數=表示式

右到左

/=

除後賦值

變數/=表示式

*=

乘後賦值

變數*=表示式

%=

取模後賦值

變數%=表示式

+=

加後賦值

變數+=表示式

-=

減後賦值

變數-=表示式

<<=

左移後賦值

變數<<=表示式

>>=

右移後賦值

變數>>=表示式

&=

按位與後賦值

變數&=表示式

^=

按位異或後賦值

變數^=表示式

|=

按位或後賦值

變數|=表示式

15

,

逗號運算子

表示式,表示式,…

左到右

從左向右順序運算

說明:

同一優先順序的運算子,運算次序由結合方向所決定。

簡單記就是:! > 算術運算子 > 關係運算符 > && > || > 賦值運算子


參考: