深入淺析C/C++?的條件編譯
1.條件編譯的時(shí)機(jī)
我們都知道vscode其實(shí)是一個(gè)編輯器,你要在上面跑C或者C++你需要配置編譯器,拿編譯器是怎樣吧一個(gè)文本文件變成一個(gè)可執(zhí)行文件的呢?
那必然是經(jīng)歷以下這四步
- 處理:宏替換,頭文件的展開(kāi),去注釋?zhuān)瑮l件編譯
- 編譯:將預(yù)處理后的源文件轉(zhuǎn)換為匯編語(yǔ)言文件,只編譯源文件,不編譯頭文件,頭文件在剛剛預(yù)處理階段已經(jīng)展開(kāi)。
- 匯編:雖然叫做匯編,但是不是轉(zhuǎn)變?yōu)閰R編代碼,而是將剛剛的匯編語(yǔ)言文件轉(zhuǎn)換為機(jī)器碼,也就是二進(jìn)制文件。
- 鏈接:將生成的二進(jìn)制代碼與庫(kù)函數(shù)以及其他目標(biāo)文件,通過(guò)鏈接器鏈接起來(lái)形成可執(zhí)行文件的過(guò)程。
分析了以上過(guò)程由此可以很清晰的得出這個(gè)結(jié)論,條件編譯是在預(yù)處理的時(shí)候發(fā)生的。
2.條件編譯的作用
條件編譯是指預(yù)處理的時(shí)候根據(jù)條件編譯的指令有條件的選擇源程序中的一部分代碼送給編譯器進(jìn)行編譯,進(jìn)行有選擇性的操作,防止宏替換的內(nèi)容重復(fù)包含。
常見(jiàn)的條件編譯指令如下:
常見(jiàn)條件編譯指令
3.#if #else #endif
#if 表達(dá)式 // code #else #endif
如果表達(dá)式為真則#if后程序段被調(diào)用
明顯發(fā)現(xiàn)第一段的色段跟第二段的色段都不一樣!肯定是第一句輸出了!
可以看到他直接call調(diào)用的就是標(biāo)準(zhǔn)命名空間下的operator類(lèi)里面的函數(shù),其實(shí)也就是 << 輸出
4.#ifndef #define #endif
#ifdef 標(biāo)識(shí)符 #define 標(biāo)識(shí)符 替換列表 // code #endef
- 一般用于檢測(cè)程序中是否已經(jīng)定義了名字為某標(biāo)識(shí)符的宏,如果沒(méi)有定義該宏,則定義該宏,并選中從 #define 開(kāi)始到 #endif 之間的程序段;
- 如果已定義,則不再重復(fù)定義該符號(hào),且相應(yīng)程序段不被選中。
我們都知道NULL在C中是一個(gè)宏,宏有時(shí)也會(huì)引起不必要的問(wèn)題在C++11中則有了nullptr,所以這塊顯示是已經(jīng)被宏過(guò)了,所有不執(zhí)行#define 到#endef的程序段所以看起來(lái)是灰色的。
紅色框框是每個(gè)函數(shù)都有的,就是主函數(shù)棧幀開(kāi)辟和銷(xiāo)毀的過(guò)程,再看中間好家伙啥都沒(méi)有,再次印證了,我們說(shuō)的如果沒(méi)有定義該宏,則定義該宏,并選中從 #define 開(kāi)始到 #endif 之間的程序段;如果已定義,則不再重復(fù)定義該符號(hào),且相應(yīng)程序段不被選中。
該條件編譯指令更重要的一個(gè)應(yīng)用是防止頭文件重復(fù)包含。
如果 f.c 源文件中包含 f1.h 和 f2.h 兩個(gè)頭文件,而 f1.h 頭文件及 f2.h 頭文件中均包含 f3.h 頭文件,則 f.c 源文件因?yàn)榘?f1.h 和 f2.h 兩個(gè)頭文件,所以中重復(fù)包含 f3.h 頭文件??刹捎脳l件編譯指令,來(lái)避免頭文件的重復(fù)包含問(wèn)題。
#ifndef _HEADNAME_H_ #define _HEADNAME_H_ //頭文件內(nèi)容 #endif
- 當(dāng)該頭文件第一次被包含時(shí),由于沒(méi)檢測(cè)到該頭文件名對(duì)應(yīng)的宏名,則定義該頭文件名對(duì)應(yīng)的宏,其值為該系統(tǒng)默認(rèn)。并且,該條件編譯指令選中 #endif 之前的頭文件內(nèi)容;
- 如果該頭文件再次被包含時(shí),由于檢測(cè)到已存在以該頭文件名對(duì)應(yīng)的宏名,則忽略該條件編譯指令之間的所有代碼,從而避免了重復(fù)包含。
5.#if #elif #else #endif
#if 條件表達(dá)式1 // code1 #elif 條件表達(dá)式2 //code 2 #else //code 3 #endif
- 功能為:先判斷條件1的值,如果為真,則程序段 1 被選中編譯;
- 如果為假,而條件表達(dá)式 2 的值為真,則程序段 2 被選中編譯;
- 其他情況,程序段 3 被選中編譯。
6.#ifdef #endif
#ifdef 標(biāo)識(shí)符 //code #endif
- 如果檢測(cè)到已定義該標(biāo)識(shí)符,則選擇執(zhí)行相應(yīng)程序段被選中編譯;
- 否則,該程序段會(huì)被忽略。
#include <iostream> using namespace std; #define PI 3.14 int main() { #ifdef PI #undef PI cout << "PI 已經(jīng)被取消宏" << endl; #endif }
如果檢測(cè)到符號(hào) PI已定義,則刪除其定義,并選中相應(yīng)的程序段。
到此這篇關(guān)于深入淺析C/C++ 的條件編譯的文章就介紹到這了,更多相關(guān)c++條件編譯內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)九大排序算法的實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言實(shí)現(xiàn)九大排序算法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01深入解析C++的循環(huán)鏈表與雙向鏈表設(shè)計(jì)的API實(shí)現(xiàn)
這篇文章主要介紹了C++的循環(huán)鏈表與雙向鏈表設(shè)計(jì)的API實(shí)現(xiàn),文中的示例對(duì)于鏈表結(jié)點(diǎn)的操作起到了很好的說(shuō)明作用,需要的朋友可以參考下2016-03-03C++使用鏈表實(shí)現(xiàn)圖書(shū)管理系統(tǒng)
這篇文章主要介紹了C++使用鏈表實(shí)現(xiàn)圖書(shū)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03C++實(shí)現(xiàn)LeetCode(8.字符串轉(zhuǎn)為整數(shù))
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(8.字符串轉(zhuǎn)為整數(shù)),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語(yǔ)言中結(jié)構(gòu)體(struct)的幾種初始化方法
相信大家都知道struct結(jié)構(gòu)體是C語(yǔ)言中非常重要的復(fù)合類(lèi)型,初始化的方法很多,那么小編下面對(duì)這些方法進(jìn)行總結(jié),便于自己和大家以后查閱,有需要的可以參考借鑒。2016-08-08聊聊C++中右值引用和移動(dòng)構(gòu)造函數(shù)的使用
這篇文章主要是來(lái)和大家一起聊聊C++中右值引用和移動(dòng)構(gòu)造函數(shù)的使用,文中通過(guò)示例進(jìn)行了詳細(xì)講解,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-07-07