C語(yǔ)言中的include很簡(jiǎn)單,但不是你想象中的簡(jiǎn)單。
之前寫過一個(gè)《C語(yǔ)言的include沒你想的那么簡(jiǎn)單》,廣受大家喜愛,詳見《C語(yǔ)言的include沒你想的那么簡(jiǎn)單(圖文版)》或《C語(yǔ)言的Include沒你想的那么簡(jiǎn)單(視頻版)》。
最近又遇到個(gè)新問題,對(duì)于同名頭文件,編譯器是怎么處理的?
我這個(gè)踩坑過程就不細(xì)說了,說多了都是淚,直接上干貨吧!
如果你嫌我啰嗦,你就直接拖到文末看截圖的結(jié)果匯總吧!
為了講清楚這個(gè)問題,我做了個(gè)實(shí)驗(yàn),編了個(gè)這樣的目錄結(jié)構(gòu)和文件:
./ │ main.c │ ├─inc1 │ inc.h │ inc1.c │ └─inc2 inc.h而這些文件內(nèi)容分別如下: (1)./main.c
// ./main.c #include(2)./inc1/inc.h#include "inc.h" extern int inc1(void); int main(void) { printf("main VAL=%d ",VAL); printf("inc1 VAL=%d ",inc1()); return 0; }
// ./inc1/inc.h #ifndef _INC_H_ #define _INC_H_ #pragma message(__FILE__) #define VAL 1 #endif(3)./inc1/inc1.c
// ./inc1/inc1.c #include "inc.h" int inc1(void) { return VAL; }(4)./inc2/inc.h
//./inc2/inc.h #ifndef _INC_H_ #define _INC_H_ #pragma message(__FILE__) #define VAL 2 #endif然后,我分別用Cygwin上的GCC、Linux上的GCC、Window上的GreenHills和Windows上的ARMCC做了測(cè)試。 首先,直接在Windows上的命令窗口上直接執(zhí)行(基于Cygwin上的GCC):
gcc .main.c.inc1inc1.c-omain得到的是
.main.c:2:10: fatal error: inc.h: No such file or directory 2 | #include "inc.h" | ^~~~~~~ compilation terminated. .inc1inc1.c:1:10: fatal error: inc.h: No such file or directory 1 | #include "inc.h" | ^~~~~~~ compilation terminated.
你會(huì)發(fā)現(xiàn)有兩個(gè)錯(cuò)誤,.main.c里面的inc.h找不到還好理解,但是.inc1inc1.c里面的inc.h也找不到?跟inc1.c同級(jí)的目錄下有一個(gè)inc.h?。?!
接下來(lái),通過編譯選項(xiàng)-I(指定頭文件路徑)加入頭文件路徑看看。
gcc .main.c .inc1inc1.c -Iinc1 -Iinc2 -o main得到的是
In file included from .main.c:2: inc1/inc.h:3:11: note: '#pragma message: inc1/inc.h' 3 | #pragma message(__FILE__) | ^~~~~~~ In file included from .inc1inc1.c:1: inc1/inc.h:3:11: note: '#pragma message: inc1/inc.h' 3 | #pragma message(__FILE__) | ^~~~~~~
兩個(gè)地方認(rèn)的都是inc1/inc.h。可以理解,-Iinc1 -Iinc2哪個(gè)先就用哪個(gè)。
接著,只指定-Iinc2,看看什么效果
gcc .main.c .inc1inc1.c -Iinc2 -o main得到的是
Infileincludedfrom.main.c:2: inc2/inc.h:3:11: note: '#pragma message: inc2/inc.h' 3 | #pragma message(__FILE__) | ^~~~~~~ In file included from .inc1inc1.c:1: inc2/inc.h:3:11: note: '#pragma message: inc2/inc.h' 3 | #pragma message(__FILE__) |^~~~~~~
好家伙,兩個(gè)地方都認(rèn)的是inc2/inc.h!.inc1inc1.c為什么不要它旁邊的inc1/inc.h呢?
難道通過-I指定路徑的優(yōu)先級(jí)是最高的?接下來(lái),通過-I指定一個(gè)空路徑試試。
gcc.main.c.inc1inc1.c-I-Iinc1-Iinc2-o main
得到的是
In file included from .main.c:2: inc2/inc.h:3:11: note: '#pragma message: inc2/inc.h' 3 | #pragma message(__FILE__) | ^~~~~~~ In file included from .inc1inc1.c:1: inc2/inc.h:3:11: note: '#pragma message: inc2/inc.h' 3 | #pragma message(__FILE__) | ^~~~~~~
看清楚這里哦-I-Iinc1-Iinc2,按剛才的推測(cè),-I的優(yōu)先級(jí)是最高的,但是這個(gè)-I是什么路徑?導(dǎo)致最終用的頭文件是inc2/inc.h??
不行,再來(lái)一發(fā),將-I改為-I./,這樣又會(huì)怎樣呢?
gcc .main.c .inc1inc1.c -I./ -Iinc1 -Iinc2 -o main
?
得到的是
Infileincludedfrom.main.c:2: inc1/inc.h:3:11: note: '#pragma message: inc1/inc.h' 3 | #pragma message(__FILE__) | ^~~~~~~ In file included from .inc1inc1.c:1: inc1/inc.h:3:11: note: '#pragma message: inc1/inc.h' 3 | #pragma message(__FILE__) | ^~~~~~~凌亂了吧,-I和-I./是不一樣的?!
等等,是不是Windows這“/”和“”不一樣,Powershell和Cygwin雜交就不一樣了?? 于是,我找了個(gè)純血的Linux+GCC試試。把路徑中的換成/:
gcc ./main.c./inc1/inc1.c-omain
./main.c:2 fatal error: inc.h: No such file or directory 2 | #include "inc.h" | ^~~~~~~ compilation terminated. In file included from ./inc1/inc1.c ./inc1/inc.h:3 note: '#pragma message: ./inc1/inc.h' 3 | #pragma message(__FILE__) | ^~~~~~~
果真,對(duì)比上面第一個(gè)案例,這里只提示一個(gè)錯(cuò)誤,說明如果不用-I指定頭文件,編譯器是可以就近找到當(dāng)前路徑的頭文件的。
接下來(lái),再看一個(gè)例子
gcc ./main.c./inc1/inc1.c-Iinc2-omain
In file included from ./main.c:2: inc2/inc.h:3:11: note: '#pragma message: inc2/inc.h' 3 | #pragma message(__FILE__) | ^~~~~~~ In file included from ./inc1/inc1.c:1: ./inc1/inc.h:3:11: note: '#pragma message: ./inc1/inc.h' 3 | #pragma message(__FILE__) | ^~~~~~~
這里說明,并不是-Iinc2指定的優(yōu)先級(jí)是最高的,./inc1/inc1.c還是能找到最近的頭文件./inc1/inc.h。
這說明什么呢?不知道,不好說,反正我就不相信網(wǎng)上說的那些,我只相信實(shí)驗(yàn)出來(lái)的結(jié)果。
小平同志說過:實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)!
那么,我就用我電腦上的其他幾個(gè)編譯器(Greenhills里的CCRH850、S32DS里的ARMCC),全部搞一遍,做個(gè)對(duì)比。我用紅框把異類標(biāo)出來(lái)了:

然后,有什么規(guī)律呢,自己總結(jié)哈!我是不記這些的,寫幾個(gè)代碼試試就知道結(jié)果了。
-
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7630瀏覽量
140475 -
編譯器
+關(guān)注
關(guān)注
1文章
1656瀏覽量
49905 -
頭文件
+關(guān)注
關(guān)注
0文章
26瀏覽量
10036
原文標(biāo)題:C語(yǔ)言的include沒你想的那么簡(jiǎn)單(同名問題)
文章出處:【微信號(hào):embedded_sw,微信公眾號(hào):嵌入式軟件實(shí)戰(zhàn)派】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
求助,COSMIC編譯器頭文件IOSTM8.H的相關(guān)問題求解
盛群ht-ide3000編譯器怎么添加自己編的頭文件
XC8編譯器頭文件定義
Bat 文件編譯器
STC單片機(jī)在KEIL編譯器中的頭文件
C語(yǔ)言中程序員編寫的頭文件和編譯器自帶的頭文件
ASM源文件編譯器軟件免費(fèi)下載

評(píng)論