每個 C 程序從 main() 開始,通過函數調用構建邏輯。函數封裝可復用代碼,支持參數傳遞與返回值,實現模塊化設計。
return_type function_name(parameter_list) { // 函數頭
declarations; // 區塊項:變量聲明
statements; // 區塊項:可執行語句
return expression; // 返回語句 (void 可省略)
}
| 組件 | 說明 |
|---|---|
| 返回類型 | void、基本類型、指針、結構體等 |
| 函數名 | 標識符,全局唯一 (外部鏈接) |
| 參數列表 | void 或 逗號分隔的 type name |
| 函數體 | { ... } 包裹的復合語句 |
| 返回語句 | return expr; 將控制權與值交還調用者 |
// 告訴編譯器:存在這樣一個函數
int add(int a, int b); // 參數名可省略
int add(int, int); // 等價
void init(void); // 明確無參
作用:允許在定義前調用,支持多文件共享接口 (頭文件)。
// 實際代碼實現
int add(int a, int b) {
return a + b;
}
int add(int a, int b) { return a + b; } // 定義在前
int main() {
add(1, 2); // 無需聲明,編譯器已見定義
}
但工程實踐強制要求頭文件聲明,便於維護與跨文件調用。
add(1, 2); // 語句調用,忽略返回值
int s = add(1, 2); // 表達式調用,接收返回值
printf("%d", add(1,2)); // 嵌套表達式
return:返回值放入寄存器/棧 → 恢復棧幀 → 跳回調用者下一條指令。
void a() { b(); }
void b() { c(); }
void c() { printf("C\n"); }
int main() { a(); } // 調用鏈: main → a → b → c
棧幀疊加,深度受限於棧大小。遞歸是特殊的自我嵌套。
void greet() {
printf("Hello!\n");
}
int main() {
greet(); // 調用
return 0;
}
stdio.h:printf, scanf, fopen, fclose...stdlib.h:malloc, free, exit, qsort, abs...string.h:strlen, strcpy, strcmp, memcpy...math.h:sqrt, sin, cos, pow... (鏈接需 -lm)使用前必包含對應頭文件,鏈接時自動解析符號。
| 原則 | 說明 |
|---|---|
| 單一職責 | 一個函數只做一件事 |
| 接口最小化 | 參數越少越好,避免全局依賴 |
| 命令查詢分離 | 修改狀態不返回值,查詢不修改狀態 |
| 錯誤處理 | 返回錯誤碼 / 輸出參數 / errno |
| 可測試性 | 純函數 (無副作用) 最易測試 |
inline 或移至 .c)。static inline 頭文件函數
// util.h
#ifndef UTIL_H
#define UTIL_H
static inline int max(int a, int b) {
return a > b ? a : b;
}
#endif
優勢:零調用開銷、類型安全、避免宏副作用、頭文件可多次包含。
函數是 C 語言模塊化的核心。掌握聲明/定義分離、調用棧機制、參數傳遞語義、返回值處理、錯誤傳播,遵循單一職責、接口最小化、可測試性原則,能構建清晰、健壯、可維護的系統代碼。標準庫函數是生產力倍增器,熟練使用 stdio/stdlib/string/math 系列。