代碼中出現 int add(int a, int b);(聲明)與 int add(int a, int b) { return a+b; }(定義),為什麼要寫兩遍?聲明有什麼用?
| 項目 | 函數聲明 | 函數定義 |
|---|---|---|
| 語法 | 返回類型 函數名(參數列表); | 返回類型 函數名(參數列表) { 函數體 } |
| 作用 | 告訴編譯器「這個函數存在、長什麼樣」 | 提供函數的具體實現邏輯 |
| 內存佔用 | 不分配代碼段內存 | 分配代碼段內存存放指令 |
| 出現次數 | 可多次(多文件包含頭文件) | 全程序僅能出現一次 |
| 典型位置 | 頭文件 .h 或文件頂部 | 源文件 .c |
C 編譯器單遍掃描源文件,調用函數時必須已知其簽名。若定義在調用之後,或定義在另一個 .c 文件,編譯器會報「隱式聲明」警告甚至錯誤。聲明解決了這個「先用後定義」的問題。
#ifndef MATH_H
#define MATH_H
int add(int a, int b); // 聲明
int subtract(int a, int b); // 聲明
#endif
#include "math.h"
int add(int a, int b) {
return a + b; // 定義
}
int subtract(int a, int b) {
return a - b; // 定義
}
#include
#include "math.h" // 引入聲明
int main() {
printf("%d\n", add(3, 5)); // 編譯器通過聲明知道 add 參數/返回類型
printf("%d\n", subtract(10, 4));
return 0;
}
main.c --編譯--> main.o (含 add 符號引用)
math.c --編譯--> math.o (含 add 符號定義)
↓ 鏈接器解析符號
最終可執行文件
#ifndef 保護 → 重複聲明錯誤。static int foo() 僅在本文件可見,無需在頭文件聲明。聲明是「介面契約」,定義是「具體實現」。良好的 C 項目遵循「頭文件只放聲明,源文件放定義」原則,實現模塊解耦、並行開發與代碼複用。初學階段養成「先寫聲明再寫定義」習慣,能避免 90% 的編譯鏈接錯誤。