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

C編程常見 15 大陷阱總結:從宏定義到未定義行為

     編輯:關於C

1. 註解缺少結束符


a = b; /* bug
c = d; /* c=d 被註解掉 */

2. 意外的賦值/布爾表達式


if (a = b) c;        // 恆真,且修改 a
if (0 < a < 5) c;    // C 中無 bool,0

3. 宏定義缺陷


#define assign(a,b) a=(char)b
assign(x, y>>8)  // 展開為 x=(char)y>>8,優先級錯誤,應加括號

4. 頭檔定義不一致


// F1.c: #define BOOL char  #include "foo.h"  → struct foo { char a; }
// F2.c: #define BOOL int   #include "foo.h"  → struct foo { int a; }
// 交互傳遞會錯位

5. 飄忽的返回值


int foo(int a) { if (a) return 1; } // a=0 時無返回值,UB

6. 位元欄佈局不可預知


struct { uint16 size:10; uint16 code:6; };
// 編譯器決定欄位順序(高位在前/低位在前)及對齊方式

7. 參數求值順序未定義


foo(ptr->member, ptr = &buf[0]); // 左右參數誰先算?編譯器決定

8. 區塊作用域易誤變


if (...) foo(); else bar();
// 加除錯輸出後:
if (...) foo(); else printf("..."); bar(); // bar() 脫離 else,永遠執行
// 解決:永遠用大括號包裹單語句區塊

9. 返回區域陣列指標


char* f() { char buf[80]; sprintf(buf, "..."); return buf; } // buf 在棧上,返回後失效

10. 副作用順序未定義


i / i++  // 可能 0 或 1
int i=1, m=0; (fun[++m])(++m); // m 遞增順序未定

11. 未初始化區域變數


void foo() { int b; if (b) ... } // b 值不定
void foo(int a) {
    BYTE* B; if (a) B=malloc(a);
    if (B) *B=a; // a=0 時 B 未初始化
}

12. 編譯環境雜訊


#define BUFFSIZE 2048
long foo[BUFSIZ]; // 拼寫錯誤:BUFSIZ (stdio.h) ≠ BUFFSIZE,編譯不報錯

13. 八進制字面值陷阱


int a[] = {001, 010, 014}; // 實際值 1, 8, 12

14. 有號字元陷阱


char c = 127; c++; // 變負數
if (c < 128) ... // 恆真

15. 標準庫不安全函式


scanf("%d %d", a, b);      // 缺 &,UB
sprintf(buf, "...");       // 易溢位,用 snprintf
gets(buf);                 // 已棄用,用 fgets

防禦清單

  • 編譯器開啟 -Wall -Wextra -Werror。
  • 宏參數與整體加括號:#define SQ(x) ((x)*(x))。
  • 永遠初始化區域變數。
  • 用 {} 包裹所有 if/else/while/for 體。
  • 不返回區域記憶體指標,改用靜態/動態/呼叫端緩衝區。
  • 避免在同一表達式中多次修改同一變數。
  • 字串操作用 snprintf/strncpy/fgets。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved