剛畢業踏入職場時,我曾滿懷自信,以為在校學到的知識足以應付工作。然而現實很快給了我一記響亮的耳光:那些曾以為「精通」的 C 語言基礎,在實際專案中不僅捉襟見肘,甚至還帶著誤導性。今天我們就以譚浩強老師經典教材《C 程序設計》中「函數」一章的範例程式為切入點,深度剖析教材代碼與工業級開發標準之間的鴻溝。
#include <stdio.h>
void main() {
float fac(int n);
int n;
float y;
printf("input an integer number: ");
scanf("%d", &n);
y = fac(n);
printf("%d!=%10.0f\n", n, y);
}
float fac(int n) {
float y;
if(n<0) {
printf("n<0, dataerror!");
} else if(n == 0 || n == 1)
f=1;
else
f=fac(n-1)*n;
return(f);
}
程式中的 n、y、f 等變數名稱極其簡短,完全無法傳達業務含義。在幾十行的教學範例中或許尚可勉強閱讀,但一旦代碼規模擴展到數千行,這類命名將嚴重拖慢維護效率。更關鍵的是,這三個變數僅聲明未初始化,在嚴謹的工程實踐中屬於嚴重違規,極易引發未定義行為。
fac 這樣的縮寫名稱,若無上下文註解幾乎無法理解其代表「階乘」。實際專案中函數數量龐大,命名必須做到見名知意。此外,範例在 main 內部聲明 fac,違反了「聲明前置、集中管理」的原則。工業界慣例是將函數原型集中放在頭文件(.h)中,既利於模組化編譯,也方便團隊協作。
當輸入負數時,函數僅打印錯誤訊息卻仍繼續執行並返回未初始化的 f,這在生產環境中極其危險。正確做法應返回錯誤碼、設置全域 errno 或拋出異常(C++),並由調用方決定後續流程。
範例中 n == 0 || n == 1 同歸於 1 雖然數學正確,但缺乏對大數溢位的防護。實際開發中需根據目標平台的 float/double 範圍設置上限,或改用迭代算法避免棧溢出風險。
教材的目標是「在有限篇幅內講清語法」,因此簡化了錯誤處理、命名規範、模組化架構等工程細節。但這恰恰是新人入職後最需要補齊的「隱性知識」。建議初學者在掌握語法後,主動閱讀開源專案(如 Linux 核心、Redis、Nginx)的代碼風格,並嘗試用 clang-format、cppcheck 等靜態分析工具檢查自己的練習代碼,養成「寫給人看、附帶能跑」的良好習慣。
金句:教材教會你「怎麼寫出能跑的代碼」,工程要求你「怎麼寫出可維護、可擴展、可測試的代碼」。