預編譯階段遇到 #include "a.h" 時,編譯器將 a.h 完整內容原文複製到包含位置。Linux下可用 gcc -E b.c 查看展開後的臨時文件。
僅在少數文件、少量函數調用時,手動在.c頂部聲明函數原型即可,無須頭文件。
函數眾多、跨文件調用頻繁時,手動維護聲明極易出錯且維護成本高。頭文件集中管理聲明,#include 自動展開,解決擴展性問題。
問題根源:多個.c包含同一.h → 預編譯後多個.c中出現同名函數定義 → 鏈接階段報 multiple definition 錯誤。
static解決機制:修飾函數為內部鏈接,僅在本編譯單元可見。不同.c展開後各自擁有獨立副本,互不衝突。
// a.h
static void test_a() { return; }
// b.c & c.c 均 #include "a.h"
// 預編譯後各自擁有 static void test_a(),鏈接不衝突
#ifndef XXX / #define XXX / #endif 不是防止多文件包含同一頭文件,而是防止單文件因嵌套包含導致同一頭文件多次展開。
// a.h: static void test_a() { }
// b.h: #include "a.h"
// c.h: #include "a.h"
// main.c: #include "b.h" + #include "c.h"
// → main.c 預編譯後出現兩個 static void test_a() → 重複定義錯誤
// a.h 加護衛宏後
#ifndef A_H
#define A_H
static void test_a() { }
#endif
// main.c 預編譯展開:
#ifndef A_H
#define A_H
static void test_a() { }
#endif
#ifndef A_H // 已定義,跳過
#define A_H
static void test_a() { }
#endif
第二次展開因 A_H 已定義被跳過,完美避免重複定義。
#pragma once)