C語言中的include很簡單,但不是你想象中的簡單。
之前寫過一個《C語言的include沒你想的那么簡單》,廣受大家喜愛,詳見《C語言的include沒你想的那么簡單(圖文版)》或《C語言的Include沒你想的那么簡單(視頻版)》。
最近又遇到個新問題,對于同名頭文件,編譯器是怎么處理的?
我這個踩坑過程就不細說了,說多了都是淚,直接上干貨吧!
如果你嫌我啰嗦,你就直接拖到文末看截圖的結(jié)果匯總吧!
為了講清楚這個問題,我做了個實驗,編了個這樣的目錄結(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做了測試。 首先,直接在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.
你會發(fā)現(xiàn)有兩個錯誤,.main.c里面的inc.h找不到還好理解,但是.inc1inc1.c里面的inc.h也找不到?跟inc1.c同級的目錄下有一個inc.h???!
接下來,通過編譯選項-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__) | ^~~~~~~
兩個地方認的都是inc1/inc.h??梢岳斫?,-Iinc1 -Iinc2哪個先就用哪個。
接著,只指定-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__) |^~~~~~~
好家伙,兩個地方都認的是inc2/inc.h!.inc1inc1.c為什么不要它旁邊的inc1/inc.h呢?
難道通過-I指定路徑的優(yōu)先級是最高的?接下來,通過-I指定一個空路徑試試。
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,按剛才的推測,-I的優(yōu)先級是最高的,但是這個-I是什么路徑?導(dǎo)致最終用的頭文件是inc2/inc.h??
不行,再來一發(fā),將-I改為-I./,這樣又會怎樣呢?
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雜交就不一樣了?? 于是,我找了個純血的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__) | ^~~~~~~
果真,對比上面第一個案例,這里只提示一個錯誤,說明如果不用-I指定頭文件,編譯器是可以就近找到當前路徑的頭文件的。
接下來,再看一個例子
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)先級是最高的,./inc1/inc1.c還是能找到最近的頭文件./inc1/inc.h。
這說明什么呢?不知道,不好說,反正我就不相信網(wǎng)上說的那些,我只相信實驗出來的結(jié)果。
小平同志說過:實踐是檢驗真理的唯一標準!
那么,我就用我電腦上的其他幾個編譯器(Greenhills里的CCRH850、S32DS里的ARMCC),全部搞一遍,做個對比。我用紅框把異類標出來了:
然后,有什么規(guī)律呢,自己總結(jié)哈!我是不記這些的,寫幾個代碼試試就知道結(jié)果了。
-
C語言
+關(guān)注
關(guān)注
180文章
7595瀏覽量
135923 -
編譯器
+關(guān)注
關(guān)注
1文章
1617瀏覽量
49019 -
頭文件
+關(guān)注
關(guān)注
0文章
25瀏覽量
9843
原文標題:C語言的include沒你想的那么簡單(同名問題)
文章出處:【微信號:embedded_sw,微信公眾號:嵌入式軟件實戰(zhàn)派】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論