標題: 用#ifndef #define #endif寫頭文件的一點總結 [打印本頁]

作者: aabbcc    時間: 2014-12-6 17:55
標題: 用#ifndef #define #endif寫頭文件的一點總結


      以前寫程序時,頭文件里都用了#ifndef xxx  #define xxx ......  #endif,因為知道這是一種條件編譯,防止重復,在多個.c文件里都可以#include "xxx.h"了,也就這么用了,但是這兩天編寫一個小程序時,照這么寫編譯連接時卻提示重復定義,于是就不知道了,明明已經(jīng)用條件編譯防止重復了呀。于是在網(wǎng)絡上各種找答案,最后發(fā)現(xiàn)了問題所在,再加上自己的一些理解,在這里做個總結,以防以后又忘了。

      #ifndef xxx  #define xxx ......  #endif這個應該是防止重復聲明而不是防止重復定義(可能這么說也不準確)。應該keil編譯器是這樣的,允許多次聲明,只要每次聲明不發(fā)生沖突(所謂沖突,舉個例子,比如在一個文件里聲明的函數(shù)為void a(void);,而在另一個文件里聲明的卻是void a(int a);,這就是函數(shù)原型沖突了。),程序就是能正常編譯連接的,因為聲明只是告訴編譯器一個符號是什么或函數(shù)原型是什么,但定義就涉及到存儲空間、地址等等這些了。還有就是他是能在同一個編譯單元中防止重復(我猜想同一個編譯單元就姑且把他認為是同一個.c文件吧,也許不對。),但是在不同的編譯單元之間他是不能傳遞的,只有在最后鏈接輸出可執(zhí)行文件時再來把編譯生成的每個.o或.obj一起鏈接,在這個過程中可能就會提示重復定義而導致無法鏈接輸出可執(zhí)行文件了。再來看看我出現(xiàn)的問題,原來我是在頭文件里定義變量了,形如:

#ifndef xxx

#define xxx

unsigned char a[]={..........};  

............

#endif

這樣,在每個.c文件里單獨編譯的時候,能正常編譯出.o文件,但是在鏈接時就會發(fā)現(xiàn)多個.o文件中包含相同的symbol a,從而導致無法正常鏈接造成程序不成功。

      解決方法就是對于一般的變量就不要在頭文件里定義,如果是想多個.c文件訪問(分享)同一個變量,那么可以在頭文件里聲明為全局的外部變量,當然關鍵字什么的大家都知道了,我也知道,形如:extern 數(shù)據(jù)類型 變量名; (不過好像用keil開發(fā)51單片機程序時數(shù)據(jù)類型bit 可以省略不寫,有點忘記了。),然后在某一個.c文件中定義一下該變量就可以了。不過記住,extern是聲明而不是定義,所以在頭文件中千萬不要給他初始化,只有在.c文件中定義時才可初始化。如果你是想在頭文件里寫一個常量大數(shù)組給后面的程序用,比如 const unsigned char image[]={......}; ,那你就只能在要用他的那個.c文件里#include "xxxx.h"了,其他地方不能在#include "xxxx.h"了,因為你是在該頭文件里定義變量。我的問題就是這種。



作者: 1250455243    時間: 2014-12-7 12:05
好。。
作者: 1250455243    時間: 2014-12-7 12:06
支持。
作者: mycookie    時間: 2014-12-9 10:35
好久沒這么細致的研究C了
作者: chweji123    時間: 2014-12-10 14:40
好。。
作者: 騰飛的龍    時間: 2015-11-2 13:07
受益匪淺,謝謝!
作者: sdlwzk    時間: 2015-11-2 22:01
之前一直模模糊糊的,不會用頭文件
作者: JY腳印    時間: 2016-2-6 23:43
有所收獲!謝謝!!
作者: wuxishun    時間: 2017-11-26 12:04
對程序看不懂,也不會編,感覺好難




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1