|
|
以前寫(xiě)程序時(shí),頭文件里都用了#ifndef xxx #define xxx ...... #endif,因?yàn)橹肋@是一種條件編譯,防止重復(fù),在多個(gè).c文件里都可以#include "xxx.h"了,也就這么用了,但是這兩天編寫(xiě)一個(gè)小程序時(shí),照這么寫(xiě)編譯連接時(shí)卻提示重復(fù)定義,于是就不知道了,明明已經(jīng)用條件編譯防止重復(fù)了呀。于是在網(wǎng)絡(luò)上各種找答案,最后發(fā)現(xiàn)了問(wèn)題所在,再加上自己的一些理解,在這里做個(gè)總結(jié),以防以后又忘了。
#ifndef xxx #define xxx ...... #endif這個(gè)應(yīng)該是防止重復(fù)聲明而不是防止重復(fù)定義(可能這么說(shuō)也不準(zhǔn)確)。應(yīng)該keil編譯器是這樣的,允許多次聲明,只要每次聲明不發(fā)生沖突(所謂沖突,舉個(gè)例子,比如在一個(gè)文件里聲明的函數(shù)為void a(void);,而在另一個(gè)文件里聲明的卻是void a(int a);,這就是函數(shù)原型沖突了。),程序就是能正常編譯連接的,因?yàn)槁暶髦皇歉嬖V編譯器一個(gè)符號(hào)是什么或函數(shù)原型是什么,但定義就涉及到存儲(chǔ)空間、地址等等這些了。還有就是他是能在同一個(gè)編譯單元中防止重復(fù)(我猜想同一個(gè)編譯單元就姑且把他認(rèn)為是同一個(gè).c文件吧,也許不對(duì)。),但是在不同的編譯單元之間他是不能傳遞的,只有在最后鏈接輸出可執(zhí)行文件時(shí)再來(lái)把編譯生成的每個(gè).o或.obj一起鏈接,在這個(gè)過(guò)程中可能就會(huì)提示重復(fù)定義而導(dǎo)致無(wú)法鏈接輸出可執(zhí)行文件了。再來(lái)看看我出現(xiàn)的問(wèn)題,原來(lái)我是在頭文件里定義變量了,形如:
#ifndef xxx
#define xxx
unsigned char a[]={..........};
............
#endif
這樣,在每個(gè).c文件里單獨(dú)編譯的時(shí)候,能正常編譯出.o文件,但是在鏈接時(shí)就會(huì)發(fā)現(xiàn)多個(gè).o文件中包含相同的symbol a,從而導(dǎo)致無(wú)法正常鏈接造成程序不成功。
解決方法就是對(duì)于一般的變量就不要在頭文件里定義,如果是想多個(gè).c文件訪(fǎng)問(wèn)(分享)同一個(gè)變量,那么可以在頭文件里聲明為全局的外部變量,當(dāng)然關(guān)鍵字什么的大家都知道了,我也知道,形如:extern 數(shù)據(jù)類(lèi)型 變量名; (不過(guò)好像用keil開(kāi)發(fā)51單片機(jī)程序時(shí)數(shù)據(jù)類(lèi)型bit 可以省略不寫(xiě),有點(diǎn)忘記了。),然后在某一個(gè).c文件中定義一下該變量就可以了。不過(guò)記住,extern是聲明而不是定義,所以在頭文件中千萬(wàn)不要給他初始化,只有在.c文件中定義時(shí)才可初始化。如果你是想在頭文件里寫(xiě)一個(gè)常量大數(shù)組給后面的程序用,比如 const unsigned char image[]={......}; ,那你就只能在要用他的那個(gè).c文件里#include "xxxx.h"了,其他地方不能在#include "xxxx.h"了,因?yàn)槟闶窃谠擃^文件里定義變量。我的問(wèn)題就是這種。
|
評(píng)分
-
查看全部評(píng)分
|