C 編譯器語法檢查相對寬鬆,給靈活性的同時埋下隱患。本文歸納 18 類高發錯誤,附錯誤代碼、正確寫法與原理解析,助你少走彎路。
int a = 5;
printf("%d", A); // 錯誤:A 未定義,C 嚴格區分大小寫
習慣:常量全大寫,變量小寫。
float a, b;
printf("%d", a % b); // 錯誤:% 僅支持整型
char c;
c = "a"; // 錯誤:"a" 是包含 'a' 和 '\0' 的字符串(2 字節)
c = 'a'; // 正確:單引號字符常量佔 1 字節
if (a = 3) // 賦值,結果為 3(真),非比較
if (a == 3) // 比較,判斷相等
習慣:常量放左邊 if (3 == a),誤寫 = 會編譯報錯。
a = 1
b = 2 // 編譯器將兩行視為一條語句,報語法錯誤
復合語句最後一句也必須加分號。
if (a % 3 == 0); // 語句在此結束
i++; // 無條件執行
for (i = 0; i < 5; i++); // 循環體為空語句
scanf(...); // 只執行一次
scanf("%d%d", a, b); // 錯誤:傳值而非地址
scanf("%d%d", &a, &b); // 正確
scanf("%d%d", &a, &b); // 輸入需用空白/換行/Tab 分隔,不能用逗號
scanf("%d,%d", &a, &b); // 格式串含逗號,輸入必須含逗號
scanf("%c%c%c", &c1, &c2, &c3);
// 輸入 "a b c" → c1='a', c2=' ', c3='b'(空格被讀入)
用 scanf(" %c", &c) 跳過前導空白。
int a = 3; float b = 4.5;
printf("%f%d", a, b); // 未報錯但輸出亂碼
scanf("%7.2f", &a); // 非法:輸入不支持精度限定
switch(grade) {
case 'A': printf("85-100");
case 'B': printf("70-84"); // 會貫穿執行
}
// 每個 case 末尾加 break
while 先判斷後執行;do-while 先執行後判斷。當條件初始為假時,前者零次執行,後者一次。
int n; scanf("%d", &n);
int a[n]; // C90 不支持,C99 支持但棧溢出風險大
動態分配用 malloc。
int a[10];
printf("%d", a[10]); // 索引 0-9,a[10] 越界
char str[20];
scanf("%s", &str); // 錯誤:數組名已是地址
scanf("%s", str); // 正確
int max(x, y)
int x, y, z; // z 應在函數體內定義
{ ... }
正確:形參列表後僅聲明類型,函數體內 { int z; ... }。
多編譯、多運行、多閱讀警告信息。開啟 -Wall -Wextra -pedantic 讓編譯器成為最強靜態分析器。