現象:無限迴圈交替 fprintf(stdout, ...) 和 fprintf(stderr, ...),stdout 輸出不顯示直到緩衝區滿/遇換行/調用 fflush,而 stderr 立即顯示。
原因:stdout 預設**全緩衝**(塊設備),stderr 預設**無緩衝**。
解決:setbuf(stdout, NULL) 或每次輸出後 fflush(stdout),或輸出帶 \n(行緩衝模式下)。
代碼:file1.c: int arr[80];,file2.c: extern int *arr;
後果:編譯通過,運行時崩潰。int * 與 int [80] 類型不同:前者是指針(需儲存地址),後者是數組(地址常量)。extern int *arr 會讀取數組前幾個元素作為指針值。
正確:extern int arr[]; 或 extern int arr[80];。
代碼:switch(a) { int b=20; case 1: printf("%d",b); }
結果:輸出隨機棧值。
原因:case 標籤是跳轉目標,聲明帶初始化的變量在作用域內但初始化被跳過。C 標準規定可聲明但不可初始化(或用塊包裹 { int b=20; ... })。
代碼:int i=10; sizeof(i++); printf("%d", i); 輸出 10。
原因:sizeof 是**編譯時運算符**,僅求表達式類型大小,不求值。i++ 不會執行。
注意:VLA(變長數組)中 sizeof 會在運行時求值,但仍不計算副作用。
代碼:y = y/*p; /* dividing y by *p */
結果:/* 被識別為註釋開始,後面代碼全被註釋掉,語句實為 y = y。
教訓:宏參數中避免 / * 組合;除法寫 y / (*p) 加空格括號。
%[^r] 行為代碼:scanf("%[^r]", dummy); 輸入 Hello, World。
結果:讀取直到遇到字符 'r'(不含),即 Hello, Wo。%[^r] 非 %[^\n](讀整行)。
正確讀行:scanf("%[^\n]", s) 或 fgets(s, sizeof(s), stdin)。
stderr 或手動 fflush。extern int arr[];。switch 中聲明變量用 { } 包裹。sizeof 中寫有副作用的表達式。scanf 格式字串仔細閱讀手冊,測試邊界輸入。