C 程序編譯報 redefinition 錯誤,主要來自兩個階段:
標準模板:
#ifndef _HEADER_NAME_H
#define _HEADER_NAME_H
/* 類型定義、宏、函數聲明、extern 變量聲明 */
#endif
機制:首次包含時宏未定義,進入內部並定義宏;再次包含時宏已定義,#ifndef 失效,內容被跳過。
命名規範:宏名通常用 _FILENAME_H 格式,大寫並加下劃線前綴,避免衝突。
錯誤示範:在 head.h 中定義 char str1[] = "char1";,多個 .c 包含該頭文件,鏈接時出現多重定義。
正確做法:
/* head.h */
#ifndef _HEAD_H
#define _HEAD_H
extern char str1[]; // 聲明
extern char str2[];
#endif
/* head.c */
#include "head.h"
char str1[] = "char1"; // 定義
char str2[] = "char2";
/* test1.c */
#include "head.h"
void test1() { printf("%s", str1); }
/* test2.c */
#include "head.h"
void test2() { printf("%s", str2); }
若某全局變量/函數僅在當前 .c 文件使用,加 static 使其具有內部鏈接屬性,不參與鏈接,從根源避免衝突:
static int private_counter = 0;
static void helper_func(void) { ... }
| 層級 | 防禦目標 | 手段 |
|---|---|---|
| 1 | 編譯期類型重定義 | 頭文件衛士 (#ifndef/#define/#endif) |
| 2 | 鏈接期實體重定義 | 頭文件只放聲明,定義放 .c,用 extern 公開 |
| 3 | 文件內部私有符號 | static 限制鏈接可見性 |
大多數程序員只知道第一層,掌握三層才能徹底解決重定義問題,構建清晰的模塊邊界。