| 文件 | 內容 | 關鍵字 |
|---|---|---|
| .c/.cpp(僅一個) | 定義並可選初始化 | 無 / 直接類型 |
| .h | 聲明 | extern |
| 其他 .c/.cpp | 包含 .h 即可使用 | #include "xxx.h" |
global.h
#ifndef GLOBAL_H
#define GLOBAL_H
extern int g_configValue; // 聲明,不初始化
extern const char* g_version; // const 也需 extern
extern struct Config g_cfg; // 結構體同理
#endif
global.c
#include "global.h"
int g_configValue = 42; // 定義+初始化
const char* g_version = "1.0.0";
struct Config g_cfg = {0}; // 零初始化
main.c
#include "global.h"
#include <stdio.h>
int main() {
printf("value=%d, ver=%s\n", g_configValue, g_version);
g_configValue = 100; // 修改全局變量
return 0;
}
int g = 0; → 多文件包含導致重複定義鏈接錯誤。extern int g = 0;:C++ 允許但極易誤解,C 標準禁止,移植性差。extern:.h 中寫 int g; → 每個編譯單元產生一個暫定定義,鏈接時可能合併也可能報錯(C99 行為不一)。#ifndef/#define/#endif 或 #pragma once。int GetConfigValue(); void SetConfigValue(int); 而非直接暴露變量,便於加鎖、日誌、驗證。g_ 前綴區分局部變量,如 g_serverPort。const 或 constexpr(C++17 inline constexpr 可直接在 .h 定義)。pthread_mutex/std::mutex)或用原子類型(std::atomic)。// global.hpp (C++17)
inline int g_configValue = 42; // 直接在頭文件定義,鏈接器自動去重
inline const char* g_version = "1.0.0";
無需 .cpp 文件,編譯器保證全程序僅有一個實體,極大簡化項目結構。