日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++ include 路径_程序员应如何理解include

發布時間:2025/3/20 c/c++ 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ include 路径_程序员应如何理解include 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

相信很多同學在學習C/C++后都有這樣的疑問,#include這句話到底是怎么意思?這句話的背后隱含了什么?我們常用的stdio.h存放在了哪里?

這篇文章就來解答這個問題。

誰來處理頭文件

有上述疑問的同學很可能是因為不熟悉一個叫預編譯器(preprocessor)的東西。

讓我們簡單的了解一下可執行程序的生成過程。

程序員寫的大家都可讀的代碼是不能被CPU直接執行的,CPU可以執行的代碼是二進制機器指令,因此一定有某個過程將程序員寫的程序轉換為了機器指令,這就是編譯器。

以上大部分同學應該都知道,但是你知道編譯器在將代碼翻譯成機器指令前其實還有一個步驟嗎?這個步驟就是預編譯。

那么預編譯都用來做什么呢?請注意,接下來是重點:

預編譯的工作非常簡單,預編譯器找到源文件中#include指定的文件,然后copy這些文件的內容并粘貼到#include這一行所在的位置。

假設在源文件a.c的第一行有一句#include ,那么預編譯器怎么處理?

預編譯找到stdio.h,把stdio.h的內容粘貼到a.c的第一行中。

是不是很簡單,完成這一過程后才是編譯器的任務。

因此我們知道,原來#include其實是告訴預編譯器把指定的頭文件內容粘貼到當前include所在的位置,也就是進行文本替換。

頭文件是不會被編譯的

從上一節中我們知道頭文件原來是被預編譯器處理的,編譯器在編譯源文件時拿到的是已經被預編譯器處理過后的源文件,因此頭文件是不會被編譯器直接處理的。

這一點要能意識到。

#include可以被放到代碼的任意位置

實際上#include可以出現在代碼中的任意一行,只不過我們習慣了在開頭使用#include,這是因為變量在聲明之前是不能被使用的。

但是我們已經知道了#include其實就是告訴預編譯器做一個簡單的文本替換,因此任何需要進行文本替換的需求其實都可以通過#include來完成的,記得博主很早在閱讀C代碼看到#include用作文本替換時大吃一驚,原來#include還可以這樣使用,類似這樣:

typedef enum { #include enum1, enum2,} test_enum;

實際上就是test.h中包含了一系列可以放到enum中的名字而已,預編譯器在處理時會把test.h中的內容在這一行展開,這樣編譯器拿到的就是完整的enum定義了。

如何查看預編譯器處理后的文件

一些好奇心強的同學可能會問那我們能不能看到預編譯器處理后的文件嗎?

答案是可以的。

假設使用的編譯器是gcc,那么使用-E選項就可以,-E選項告訴編譯器在處理源文件時不要編譯、不要匯編和鏈接,僅預處理。

$ gcc -E test.c

使用上述命令就可以看到預處理后的文件是什么樣子的。

其它編譯器肯定也能找到類似的支持。

兩種使用頭文件的方式

你一定注意到了,其實#include有兩種寫法,一種是#include<>;另一種是#include “”,即:

#include #include "code.h"

那么這兩種使用方法有什么區別嗎?

注意,知道這兩種用法背后的含義對于程序員來說是非常重要的。

預編譯器要想處理頭文件首先必須要能找到這個頭文件。

如果一個頭文件放到了<>中,那么預編譯器會在系統頭文件所在的路徑下開始找,在Linux下這個路徑是/usr/include,讓我們來看一下/usr/include這個文件夾下都有什么:

我們可以看到這里有很多頭文件,注意劃紅線的位置,原來我們常用的#include就放在了這里,現在終于解答一個困擾了我們很久的問題。

實際上這里存放的就是標準庫頭文件,關于標準庫參見《程序員應如何理解標準庫》。

接下來就簡單了,如果頭文件被放到了雙引號“”中呢?

很顯然只不過就是預編譯器搜索路徑不再是系統頭文件所在路徑了,而是以源文件所在位置開始查找,當然不同的編譯器策略可能稍有差別。

當在這些路徑中找不到include的頭文件時就會拋出錯誤“fatal error: ***.h: No such file or directory”,這是程序員經常遇到的錯誤,現在你應該知道怎么排查這類問題了吧。

為什么要使用頭文件

最后來回答一下為什么的問題,是啊,程序員為什么要使用頭文件這種東西呢?

還記得開始學編程時用的經典的HelloWorld程序嗎?

#include int main() { printf("hello world\n"); return 0; }

在這段簡單的代碼中實際上如果我們不使用printf函數打印東西的話根本就不需要stdio.h,那么程序就變成了這樣:

int main() { return 0;}

注意該代碼不依賴任何頭文件,不要懷疑,該代碼可以正確的編譯運行。

如果程序員愿意的話可以把項目所有實現代碼都放到這個文件中,就像這樣:

void funA() { ...}void funB() { ...}int main() { ... funA(); funB();}

該程序不依賴任何頭文件,所有實現代碼都放到了一個源文件,而對于現在稍微有規模的軟件項目其代碼量都在十幾萬、甚至上百萬,你能想象一個包含十幾萬行代碼的源文件是一種怎樣的場景嗎?

這樣的代碼有沒有可能寫出呢?

答案是有的,只要這個項目的程序員對于所有使用到的輪子都從頭到尾重復打造一遍,比如自己實現用到的標準庫中的函數,比如printf,自己實現各種數據結構等等等等。

而且這樣的項目有沒有辦法維護呢?

答案是有的,重賞之下必有勇夫,只要開出百萬年薪必然有人入坑。

因此,我們發現這樣寫代碼不但要重復造輪子還極其難以維護。

所以現在的軟件工程一項原則就是復用,能復用其它人的代碼絕不會自己重復寫一份。

那么問題來了,我們該怎樣使用其它人寫好的代碼呢?

我們該調用哪些函數,這些函數的返回值是什么?參數是什么?

頭文件幫程序員解決了上述問題。

頭文件里仔仔細細的寫好了該模塊有哪些函數可供使用者調用、返回值是什么、參數是什么,但頭文件中并不會包含實現,這是因為C/C++語言不要求函數的聲明和實現必須呆在同一個地方。

因此你會看到,頭文件的作用其實是和我們常用的說明書沒什么區別。

現在問題就簡單了,我們再也不需要一個包含幾十萬代碼的源文件了,程序員可以將其模塊化,各個團隊負責一個模塊,每個模塊會編寫一些頭文件供其它人調用,同時每個模塊只寫一次,其它團隊有需要可以直接使用,最后再把各個模塊組合起來,這樣大家各司其職又能最大程度實現代碼復用。

最后值得注意的一點就是,頭文件其實是讓編譯器知道該怎樣生成調用函數的機器指令,而真正將相關代碼打包到可執行程序的是鏈接器,因此作為程序員不僅需要指定用哪些頭文件,還要指定頭文件中函數的實現代碼,也就是程序員常說的庫在哪里。

總結

現在大家應該對頭文件有一個全面的認知了吧,原來include只是告訴預編譯器在當前位置展開頭文件,同時我們也知道了兩種include的使用方法及其區別,最后我們了解了為什么要發明頭文件這種技術,希望這篇文章能幫你徹底理解頭文件。

總結

以上是生活随笔為你收集整理的c++ include 路径_程序员应如何理解include的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。