函數是 C 語言模塊化、復用、抽象的核心機制。本文系統梳理函數聲明定義、參數傳遞語義(值傳遞本質)、遞歸與尾調用、內聯函數、可變參數(stdarg.h)、函數指針回調、屬性擴展(GCC/Clang),並給出工程級設計原則與常見陷阱。
// 聲明:告知編譯器名稱、返回類型、參數類型
int add(int a, int b); // 參數名可省略
int add(int, int); // 等價
// 定義:提供函數體
int add(int a, int b) { return a + b; }
C89 允許未聲明直接調用,默認 int func()。C99 起**必須先聲明**,否則編譯錯誤。
int foo(); // 老式:參數未指定,調用時不檢查(危險) int bar(void); // 標準:無參數,調用帶參報錯
void swap(int *a, int *b) {
int t = *a; *a = *b; *b = t;
}
int x=1, y=2;
swap(&x, &y); // 傳遞地址值,函數通過解引用修改原對象
void foo(int arr[10]); // 等價於 void foo(int *arr); // 等價於 void foo(int arr[]); // 長度信息丟失,必須額外傳 len
int strlen(const char *s); // 承諾不修改 s 指向的內容 void process(const int *arr, size_t n); // 僅讀數組
unsigned long long fact(unsigned n) {
return n <= 1 ? 1 : n * fact(n-1);
}
特性 inline 函數 宏 類型安全 ✓ ✗ 副作用安全 ✓(參數求值一次) ✗(多次求值) 調試可見 ✓ ✗ 編譯期計算 ✓(constexpr C++/常量傳播) ✓ 代碼膨脹 編譯器控制 完全展開 3. 現代最佳實踐
#includevoid log_msg(const char *fmt, ...) { va_list ap; va_start(ap, fmt); // 最後一個固定參數 vprintf(fmt, ap); // 傳遞 va_list va_end(ap); // 清理 } 2. 類型安全缺失與替代方案
_Generic 可構建類型安全可變參數fmt 庫(C++)/ 自定義類型安全日誌 APIint (*cmp)(const void *, const void *); // 指向函數的指針 void (*handler)(int); // 信號處理器類型
qsort(base, nmemb, size, cmp); bsearch(key, base, nmemb, size, cmp);
struct Animal {
void (*speak)(struct Animal *);
void (*move)(struct Animal *);
};
void dog_speak(struct Animal *self) { puts("Woof"); }
struct Animal dog = { dog_speak, dog_move };
dog.speak(&dog); // 多態調用
| 屬性 | 用途 | 示例 |
|---|---|---|
| noreturn | 永不返回,優化調用點 | void abort(void) __attribute__((noreturn)); |
| pure | 無副作用,僅依賴參數/全局讀 | int square(int) __attribute__((pure)); |
| const | 純函數+無全局讀,結果可緩存 | int hash(int) __attribute__((const)); |
| malloc | 返回非別名指針,優化別名分析 | void *alloc(size_t) __attribute__((malloc)); |
| warn_unused_result | 忽略返回值發出警告 | int open(...) __attribute__((warn_unused_result)); |
| format(printf, m, n) | 格式字符串檢查 | void log(const char*,...) __attribute__((format(printf,1,2))); |
| cleanup | 變量作用域結束自動調用 | __attribute__((cleanup(free))) |
memcpy(dst, src, n)errno、_Thread_local 錯誤上下文const 盡量加/** @brief ... @param ... @return ... */C 語言函數機制樸素而強大。**值傳遞本質、指針模擬引用、遞歸轉迭代、內聯權衡、可變參數類型安全、函數指針多態、屬性引導優化**,構成了系統級開發的函數式工具箱。現代 C 開發建議:頭文件 static inline 小函數、.c 文件 __attribute__ 關鍵函數、回調用函數指針、避免可變參數公共 API、錯誤碼統一風格。