C語言中重複定義的問題
幾個基本知識:
1、標頭檔案:標頭檔案的作用在於編譯時,會在#include<*.h>位置處展開,所以如果有多個.c檔案include同一個標頭檔案(很常見),如果標頭檔案編寫時不進行處理,出現重複定義是不可避免的。尤其是當一個專案分成多個模組的時候。
2、一般,把函式、變數、結構體、類等放在.c或者.cpp檔案中,編譯生成.o、.dll等給其他檔案使用。
3、標頭檔案一般放函式、變數、類的宣告。
4、不允許被其他檔案使用的函式用static定義,否則預設為extern
5、一般不要在標頭檔案中定義變數、函式、類,否則容易產生重複定義。
6、要使用其他模組(檔案)定義的函式、變數等,直接包含其標頭檔案。
例
//a.c
#include<stdio.h>
void Print(void){
printf("test\n");
}
//a.h
void Print(void); //宣告Print函式
//b.c
#include<a.h>
main(){
Print();
}
編譯後執行,打印出test
我們經常遇到這樣一種情況,需要定義一個結構體,這個結構體可能要在多個檔案中使用。一般我們把結構體定義在標頭檔案中,其他檔案要使用時,只需要
include就可以了,不幸的是,編譯的時候會出現重複定義的提示。原因很簡單,多次include展開時,標頭檔案中定義的結構體會被多次定義。例如:在f1.c中有#include<a.h>,f2.c中也有#include<a.h>,那麼a.h就會展開兩次,結構體就重複定義了,這時候就需要對標頭檔案進行處理了。
例:
1、在 struct.h中定義了一個結構體sqlist
//struct.h
#ifndef STRU_H //這個STRU_H是隨意取的,但是最好是有意義並且不與其他重複
#define STRU_H
typedef struct{
int length;
int listsize;
}Sqlist;
#endif
2、在檔案f1.c中定義了一個函式Initlist對結構體進行初始化操作
//f1.c
#include<struct.h>
#include<stdio.h>
void Initlist(Sqlist *L){
L->length=0;
L->listsize=100;
}
3、在標頭檔案f1.h中對函式進行宣告
//f1.h
#ifndef FUN1_H
#define FUN1_H
void Initlist(Sqlist *L);
#endif
4、在檔案f2.c中有main函式定義了一個結構體型別變數,並呼叫外部函式Initlist進行初始化
//f2.c
#include<stdio.h>
#include<struct.h>//為了使用結構體型別
#include<f1.h>//為了呼叫外部函式
void main(){
Sqlist La;
Initlist(&La);
printf("%d,%d\n",La.length,La.listsize);
}
5、正確編譯,執行,得到結果 0,100