頭文件是模塊的公共接口契約,源文件是私有實現細節。嚴格分離才能實現低耦合、高內聚。
// mymath.h
#ifndef MYMATH_H
#define MYMATH_H
extern int Global_A; // 聲明全局變量
extern void fun(void); // 聲明接口函數
#endif
// mymath.c
#include "mymath.h"
int Global_A; // 定義全局變量
void fun(void) { ... } // 實現
缺點:全局變量散落各模塊,難以追蹤、易衝突、破壞封裝。
// Globel_Var.h —— 唯一全局變量聲明處
#ifndef GLOBAL_VAR_H
#define GLOBAL_VAR_H
extern int speed;
extern int torque;
// ... 所有跨模塊共享變量
#endif
// Globel_Var.c —— 唯一全局變量定義處
#include "Globel_Var.h"
int speed;
int torque;
使用時:
// aa.h
#include "Globel_Var.h"
extern void fun(void);
// aa.c
#include "aa.h"
void fun(void) { speed = 100; } // 直接用
// bb.c
#include "bb.h"
#include "aa.h" // 間接包含 Globel_Var.h
void fun_1(void) { fun(); torque = 200; }
優勢:單一真實來源,易審計、易重構、避免重複定義錯誤。
extern 聲明。static 修飾。#ifndef MODULE_H #define MODULE_H ... #endif 或 #pragma once。abc.c 對應 abc.h。extern 變量:優先提供 get_xxx()/set_xxx() 訪問函數,保護數據不變量。#include 其他模塊的接口頭文件,除非參數/返回值需完整類型定義。前向聲明 struct Foo; 即可用於指標參數。windows.h, pthread.h 放在 .c 中。當一個邏輯模塊拆分為多個 .c 文件 (如 parser_lex.c, parser_yacc.c):
parser.h 對外暴露接口。parser_internal.h (不對外發布)。<系統名>_<模塊名>.h。config.h, limits.h, error_codes.h。#define, enum, 類型別名。#include "module.h" (驗證 .h 自給自足)。static 限制作用域。extern (那是 .h 的事)。
project/
├── include/ # 公開接口頭文件
│ ├── core.h
│ ├── network.h
│ └── storage.h
├── src/ # 源文件 (不公開)
│ ├── core/
│ │ ├── core.h # 內部接口
│ │ ├── core.c
│ │ └── utils.c
│ ├── network/
│ └── storage/
├── common/ # 共享說明性頭文件
│ ├── config.h
│ └── error_codes.h
├── Globel_Var.h/c # 全局變量統一管理
└── main.c
遵循這套規範,配合靜態分析工具 (Cppcheck, Clang-Tidy) 和編譯器警告 (-Wmissing-prototypes -Wstrict-prototypes),能構建出可維護、可擴展、可團隊協作的高質量 C 專案。