while (1) {
fprintf(stdout, "hello-std-out"); // 無\n
fprintf(stderr, "hello-std-err"); // 無緩衝
sleep(1);
}
現象:stderr立即顯示,stdout延遲甚至不顯示。
原理:
修正:
fprintf(stdout, "hello-std-out\n"); // 加換行 // 或 fflush(stdout); // 手動刷新 // 或 setvbuf(stdout, NULL, _IONBF, 0); // 設置無緩衝
// file1.c
int arr[80];
// file2.c
extern int *arr; // ❌ 錯誤:指針 ≠ 數組
int main() { arr[1] = 100; } // 運行時崩潰
原因:編譯器按指針生成代碼(間接訪問),實際內存佈局是連續整數(直接訪問)。
正確:extern int arr[]; 或 extern int arr[80];
int a = 1;
switch (a) {
int b = 20; // ⚠️ 編譯警告:unreachable code
case 1:
printf("%d", b); // 輸出垃圾值
}
原理:case標號本質是goto目標,直接跳過聲明初始化語句。
修正:用塊作用域包裹:
switch (a) {
case 1: {
int b = 20; // ✅ 安全
printf("%d", b);
} break;
}
int i = 10;
printf("%d\n", sizeof(i++)); // 輸出4(32位int大小)
printf("%d\n", i); // 輸出10(i未自增!)
本質:sizeof是編譯期運算符,僅求類型大小,不求值表達式(VLA除外)。
#define PrintInt(expr) printf("%s : %d\n", #expr, (expr))
int y = 100, *p = malloc(sizeof(int));
*p = 10;
y = y/*p; // ❌ 誤為 y = y / *p; 實際 /* 開啟註釋!
PrintInt(y); // 輸出100
雙重教訓:
y = y / *p;PrintInt(i++)展開後i++執行兩次char buf[80];
scanf("%[^r]", buf); // 讀取直到字符'r'(不含r)
// 輸入 "Hello, World" → 讀取 "Hello, Wo" (遇r停止)
%[^r]為掃描集:匹配非'r'字符序列,遇'r'、EOF或寬度限制停止。
| 編號 | 核心點 | 關鍵詞 |
|---|---|---|
| 1 | stdout/stderr緩衝模式差異 | 行緩衝/塊緩衝/無緩衝 |
| 2 | extern數組必須聲明為數組類型 | 指針≠數組 |
| 3 | switch跳過聲明初始化 | 塊作用域包裹 |
| 4 | sizeof不求值無副作用 | 編譯期運算符 |
| 5 | 宏參數副作用/註釋吞噬 | 空格分隔/無副作用 |
| 6 | scanf掃描集語法 | %[^chars] |