C語言的include沒你想的那么簡單
時間:2024-01-16 來源:華清遠見
C語言中的include很簡單,我們認為就是用來包含頭文件的,
#include命令是預處理命令的一種,預處理命令可以將別的源代碼內容插入到所指定的位置;可以
標識出只有在特定條件下才會被編譯的某一段程序代碼;
可以定義類似標識符功能的宏,在編譯時,預處理器會用別的文本取代該宏。但它真的是這么簡單嗎?
#include<stdio.h>
#include"drv_led.h"//
我們在寫程序時對于它的用法就如上面寫的一樣,在需要用到某個函數時,就引用一下函數聲明的頭
文件,那上面兩種寫法有什么不一樣呢:
使用尖括號<>和雙引號""的區別在于頭文件的搜索路徑不同:
1、使用尖括號<>,編譯器會到系統路徑下查找頭文件;
2、使用雙引號"",編譯器首先在當前目錄下查找頭文件,如果沒有找到,再到系統路徑下查找
有些人還將整個所有的.h文件全部包含在一個includes.h的頭文件中,然后在其他.c文件里
面,就直接#include"includes.h"。這么寫看視好像簡單化了程序但是我們從上面的分析看,
#include就是將它后面包含的頭文件源文件,全部展開。所以上這樣寫法帶來的最直接的感
受就是編譯過程慢!includes.h里包含得越多就越慢!另外一個隱含的問題是,會造成include
里的內容混亂,頭文件里的內容全部是全局的了。不建議這么去操作。那么如果一個頭文件,
有多個地方被使用,會不會被重復包含多次呢?重復包含頭文件會導致編譯報錯,因為重復
include,就相當于把頭文件重復展開了多次,C語言中有些定義是不允許重復多次的,那用
什么辦法可以解決呢?可以用#ifdef...#endif這種方式規避。例如
#ifdef_DEBUG_
#defineMY_HEADER"myled.h"
#else
#defineMY_HEADER"mydelay.h"
#endif
#includeMY_HEADER
上面這種寫法是當上述程序代碼進入預處理時,如果DEBUG宏已被定義,那么預處理器會插入
myled.h的內容;如果還沒定義,則插入mydelay.h的內容。
那么預處理器如何找到頭文件
由給定的C語言實現版本決定#include命令所指定文件的搜索路徑。同時,也由實現版本決定文
件名是否區分大小寫。對于命令中使用尖括號指定的文件(),預處理器通常會在特定的系統路徑下
搜索,例如,在Unix系統中,會搜索路徑/usr/local/include與/usr/include。
對于命令中用雙引號指定的文件("文件名"),預處理器通常首先在當前目錄下尋找,也就是包含該
程序其他源文件的目錄。如果在當前目錄下沒有找到,那么預處理器也會搜索系統的include路徑。
文件名中可以包含路徑。但如果文件名中包含了路徑,則預處理器只會到該目錄下尋找。
你也可以通過使用編譯器命令行選項,或在環境變量(該變量通常稱為INCLUDE)中加入搜索路徑,
為#include命令指定自己的搜索路徑。
但其實#include在C語言中,算是預編譯指令(preprocessingdirective)范疇,在C99標
準中它是由一個源文件和一些由#include包含著的headers和sourcefiles,通過預編譯后,變成
一個叫translationunit的東西。所以從這里可以看出來,#include不但可以包含headers,還可
以包含源文件,也就是說我們在程序里面也可以像下面這么寫
#include"add.h"
#include"minus.c"
除了*.h和*.c文件,我還可以這么寫
//main.c#include"multiply.txt"
intmain(void){inte=multiply(2,2);return0;}
甚至,這樣也行
//main.c#include"devide.fxxk"
intmain(void){intf=devide(2,2);return0;}
我們一般是將#include放在文件上方,其實也可以放中間
//main.cintmain(void){#include"squel.xx"intg=squel(2,2);return0;}
那能不能將data.txt換成二進制形式的data.bin呢?這種就不行,因為編譯器在預編譯階段
只認得是text文本。好吧……你不是說這是個預編譯指令嗎,我很好奇,#include預編譯后
成啥樣子的?這好辦,動動手指頭,一個gcc-E命令即可搞定。就以上面第一個例子,命令
行執行gcc./main.c-E-omain.i
#0".\main.c"#0""#0"<命令行>"#1".\main.c"
#1"add.h"1externintadd(inta,intb);#3".\main.c"2#1"minus.c"1intminus(inta,intb){return
a-b;}#4".\main.c"2
intadd(inta,intb){returna+b;}
intmain(void){intc=add(1,2);intd=minus(2-1);return0;}
看到了吧,#include就是把它后面的文件內容直接include進來。

