C語言的自增自減運算子問題

2021-08-15 23:19:04 字數 3602 閱讀 6244

c語言的自增++,自減--運算子對於初學者來說一直都是個難題,甚至很多老手也會產生困惑,最近我在網上看到乙個問題:

#include

void main() /*主函式*/

結果是什麼?

而後eric搜了一下後發現,類似的問題很多,也就是說對自增自減運算子感到迷惑是乙個普遍存在的問題,基於此,eric決定對自增自減運算子做個小小的解析,希望能給c語言愛好者們提供參考,解決對此問題的困惑。

自增自減運算子語法

自增運算子 ++ 使運算元的值加1,其運算元必須為(可簡單地理解為變數)。對於自增就是加1這一點,eric想大家都不會有什麼疑問。

問題在於:++ 可以置於運算元前面,也可以放在後面,如:

++i;

i++ ;

++i表示,i自增1後再參與其它運算;而i++ 則是i參與運算後,i的值再自增1.

自減運算子--與之類似,只不過是變加為減而已,故不重述。

例項剖析

下面我們通過一些例項來深入理解自增運算子的特性,自減運算子同理自悟

例一:int i=3;

int j=4;

i++;

++j;

printf("%d, %d\n", i, j);

int i=3;

int j=4;

int a = i++;

int b = ++j;

printf("%d, %d\n", a, b);

結果又是多少呢?這裡就開始體現出++前置與後置的區別了,結果是3,5.結合此例,我們回頭再來理解一下"++前置:i自增1後再參與其它運算;++後置:i參與運算後,i的值再自增1".很明顯,a = i++;由於是先執行賦值運算,再自增,所以結果是a=3,i=4;而b = ++j;

則因先自增,然後再賦值,所以b,j均為5.

其實基本道理就這麼簡單了,但在更複雜點的情況下又會如何呢,請看:

例二:int i=3;

int j=4;

int a = i++ + i++;

int b = ++j + ++j;

printf("%d, %d\n", a, b);

問題又來了,i++ + i++是先自增一次,相加,再自增,然後賦值呢,還是先相加賦值然後自增兩次呢。另外,++j又將如何表現呢?

結果是:6,12

這下明白了,原來 i++的理解應該是執行完整個表示式的其他操作後,然後才自增,所以例子中的a=3+3=6;而後i再自增2次,i=5;相反,++j是先自增然後再參加其它運算,所以b=6+6=12.

到此,是否就徹底明了了呢?然後回到引子中的問題

例三:int i=3;

int j=4;

int a = i++ + i++ + i++;

int b = ++j + ++j + ++j;

printf("%d, %d\n", a, b);

有人可能會說,這很簡單,我全明白了:a=3+3+3=9,i=6,b=5+5+5=15,j=5.真的是這樣嗎?

結果卻是:9,19

這下可好,又糊塗了。對於a = i++ + i++ + i++;我們已經沒有疑問了,++後置就是執行完整個表示式的其他操作後,然後才自增,上例中也得到了驗證,但 b = ++j + ++j + ++j;又該如何理解呢?

原理表示式中除了預演算法本身的優先順序外,還有乙個結合性問題。在++j + ++j + ++j;中,因為存在兩個同級的+運算,根據+運算子的左結合性,在編譯時,其實是先處理前面的(++j + ++j)這部分,然後再將此結果再和++j相加。具體過程參見彙編**:

int b = ++j + ++j + ++j;

0040b7dd mov ecx,dword ptr [ebp-8]

0040b7e0 add ecx,1

0040b7e3 mov dword ptr [ebp-8],ecx // 第乙個++j

0040b7e6 mov edx,dword ptr [ebp-8]

0040b7e9 add edx,1

0040b7ec mov dword ptr [ebp-8],edx // 第二個++j

0040b7ef mov eax,dword ptr [ebp-8]

0040b7f2 add eax,dword ptr [ebp-8] // ++j + ++j

0040b7f5 mov ecx,dword ptr [ebp-8]

0040b7f8 add ecx,1

0040b7fb mov dword ptr [ebp-8],ecx // 第三個++j

0040b7fe add eax,dword ptr [ebp-8] // ++j + ++j + ++j

0040b801 mov dword ptr [ebp-10h],eax // 賦值給b

另外我們看看a = i++ + i++ + i++;的彙編**:

int a = i++ + i++ + i++;

0040b7b6 mov eax,dword ptr [ebp-4]

0040b7b9 add eax,dword ptr [ebp-4] // i+i

0040b7bc add eax,dword ptr [ebp-4] // i+i+i

0040b7bf mov dword ptr [ebp-0ch],eax // 賦值給a

0040b7c2 mov ecx,dword ptr [ebp-4]

0040b7c5 add ecx,1

0040b7c8 mov dword ptr [ebp-4],ecx // 第一次i++

0040b7cb mov edx,dword ptr [ebp-4]

0040b7ce add edx,1

0040b7d1 mov dword ptr [ebp-4],edx // 第二次i++

0040b7d4 mov eax,dword ptr [ebp-4]

0040b7d7 add eax,1

0040b7da mov dword ptr [ebp-4],eax // 第三次i++

果然不出所料。到此,++運算子前置後置的問題應該徹底解決了。

為了驗證一下上述結論,我們再看:

例四:int i=1;

int j=1;

int a = i++ + i++ + i++ + i++ + i++ + i++ + i++; // 七個

int b = ++j + ++j + ++j + ++j + ++j + ++j + ++j;

printf("%d, %d\n", a, b);

printf("%d, %d\n", i, j);

規則就是規則,咱的計算機可不是黑客帝國的母體,總是要遵循它的

a = 1+1+1+1+1+1+1 = 7, i=8

b = 3+3+4+5+6+7+8 = 36, j=8

一切ok,恭喜你還生活在21世紀的地球,不用擔心matrix控制你的思維和生活

注:以上結果及解發布自vc編譯器,但對於++這個問題是和編譯器的解析有關的,不同廠家可能理解不一致,因手頭沒有其他開發環境,暫無法做全面分析,本文只是為了說明++,--這運算子的一些特性,尤其是前置後置的區別這個問題。類似的問題如果有困惑,最好是寫程式做試驗解決,請勿生搬硬套。謝謝!在實際的程式設計實踐中,類似的問題除了要試驗搞清外,eric認為應該盡量避免引入環境相關的程式設計技巧。

自增自減運算子

自增自減運算子 i 先使用i,然後i i 1 i 先使用i,然後i i 1 i 先i i 1然後使用i i 先i i 1 然後使用i 以下使用vc下除錯的結果,不同的編譯器可能有不同的結果。i 3 例1printf d i 結果輸出4 例2printf d i 結果輸出3 例3printf resu...

自增 ,自減 運算子

自增1運算子記為 其功能是使變數的值自增1。自減1運算子記為 其功能是使變數值自減1。自增1,自減1運算子均為單目運算,都具有右結合性。可有以下幾種形式 i i自增1後再參與其它運算。i i自減1後再參與其它運算。i i參與運算後,i的值再自增1。i i參與運算後,i的值再自減1。在理解和使用上容易...

C 基礎 自增自減運算子

注 當自增自減運算子所在的表示式或語句中只含一種操作時 即單一表示式 則其字首和字尾功能對程式的作用時一樣的 而當含有兩個或兩個以上操作時,在考慮各個運算子的優先級別和結合性的基礎上,則其字首和字尾的功能對程式的作用時不一樣的。1 為了提高程式的效率,需要用技巧把程式寫得盡可能簡潔一些,但這樣有可能...