首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C 語言前綴/後綴自增自減運算符深度解析與陷阱避坑指南

     編輯:關於C

運算符分類與核心差異

C 語言提供四種自增/自減運算符,核心差異在於「值的計算時機」與「副作用發生時機」:

運算符名稱語義
++i前綴自增先自增 1,再參與運算,值為新值
--i前綴自減先自減 1,再參與運算,值為新值
i++後綴自增先參與運算(值為舊值),再自增 1
i--後綴自減先參與運算(值為舊值),再自減 1

基礎範例與輸出解析

前綴自增 ++i

int i = 8;
printf("%d\n", ++i); // 輸出 9
// 說明:i 先自增為 9,再輸出

後綴自增 i++

int i = 8;
printf("%d\n", i++); // 輸出 8
printf("%d\n", i);   // 輸出 9
// 說明:先用舊值 8 參與運算,輸出後 i 變為 9

前綴自減 --i

int i = 8;
printf("%d\n", --i); // 輸出 7

後綴自減 i--

int i = 8;
printf("%d\n", i--); // 輸出 8
printf("%d\n", i);   // 輸出 7

複合表達式陷阱:負號結合與多重副作用

-i++ 與 -i--

int i = 8;
printf("%d\n", -i++); // 輸出 -8,i 變 9
// 解析:等價於 -(i++),先取 i 舊值 8 加負號得 -8,再 i 自增

int i = 8;
printf("%d\n", -i--); // 輸出 -8,i 變 7
// 解析:等價於 -(i--),先取舊值 8 加負號,再 i 自減

-(++i) 與 -(--i)

int i = 8;
printf("%d\n", -(++i)); // 輸出 -9,i 變 9
// 解析:先自增得 9,再加負號

int i = 8;
printf("%d\n", -(--i)); // 輸出 -7,i 變 7
// 解析:先自減得 7,再加負號

多重副作用的未定義行為

警告:單一表達式中對同一變數多次修改屬於未定義行為(UB),不同編譯器結果可能不同。以下僅供理解運算符結合性,實際編程中嚴禁使用。

(i++) + (i++) + (i++)

int i = 5, p = (i++) + (i++) + (i++);
// 可能結果:p = 5+5+5 = 15,i = 8
// 實際取決於編譯器求值順序

(++i) + (++i) + (++i)

int i = 5, p = (++i) + (++i) + (++i);
// 可能結果:i 先增至 7,前兩項 7+7=14,第三項增至 8,總和 22,i=8

指標運算符優先級與結合性

表達式結合順序語義
*p++*(p++)先取 *p 值,再將指標 p 遞增
*p--*(p--)先取 *p 值,再將指標 p 遞減
(*p)++先取 *p 值參與運算,再將所指值自增值為舊值,所指記憶體內容 +1
(*p)--先取 *p 值參與運算,再將所指值自減值為舊值,所指記憶體內容 -1
*++p*(++p)先將指標 p 遞增,再取新位置的值
*--p*(--p)先將指標 p 遞減,再取新位置的值
++*p++(*p)先取值,再將所指值自增,值為新值
--*p--(*p)先取值,再將所指值自減,值為新值
*(p++)同 *p++括號僅為強調結合性
*(p--)同 *p--括號僅為強調結合性

實戰範例:指標與陣列遍歷

int a[5] = {1,8,10,5,2};
int *p = a;
printf("%d\n", *p++); // 輸出 1,p 指向 a[1]
printf("%d\n", *p);   // 輸出 8

p = &a[1];
printf("%d\n", *p--); // 輸出 8,p 指向 a[0]
printf("%d\n", *p);   // 輸出 1

p = a;
printf("%d\n", (*p)++); // 輸出 1,a[0] 變 2
printf("%d\n", *p);     // 輸出 2

p = a;
printf("%d\n", (*p)--); // 輸出 1,a[0] 變 0
printf("%d\n", *p);     // 輸出 0

p = a;
printf("%d\n", *++p);   // p 先指向 a[1],輸出 8

p = &a[1];
printf("%d\n", *--p);   // p 先指向 a[0],輸出 1

最佳實踐建議

  1. 避免複雜表達式:單一語句中不要對同一變數進行多次自增/自減
  2. 明確語義:需要先運算後副作用用後綴,先副作用後運算用前綴
  3. 指標運算:記住 [] 優先級高於 *,*p++ 等價 *(p++)
  4. 啟用編譯器警告:-Wall -Wextra -Wsequence-point 可捕捉多數 UB
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved