前言
—般情況下,C語言源程序中的每一行代碼.都要參加編譯。但有時(shí)候出于對(duì)程序代碼優(yōu)化的考慮,希望只對(duì)其中一部分內(nèi)容進(jìn)行編譯。此時(shí)就需要在程序中加上條件,讓編譯器只對(duì)滿足條件的代碼進(jìn)行編譯,將不滿足條件的代碼舍棄,這就是條件編譯,相關(guān)的預(yù)編譯指令如下:
#define |
定義一個(gè)預(yù)處理宏 |
#undef |
取消宏的定義 |
#if |
編譯預(yù)處理中的條件命令,相當(dāng)于C語法中的if語句 |
#ifdef |
判斷某個(gè)宏是否被定義,若已定義,執(zhí)行隨后的語句 |
#ifndef |
與#ifdef相反,判斷某個(gè)宏是否未被定義 |
#elif |
若#if, #ifdef, #ifndef或前面的#elif條件不滿足,則執(zhí)行#elif之后的語句,相當(dāng)于C語法中的else-if |
else |
與#if, #ifdef, #ifndef對(duì)應(yīng),若這些條件不滿足,則執(zhí)行#else之后的語句,相當(dāng)于C語法中的else |
endif |
#if, #ifdef, #ifndef這些條件命令的結(jié)束標(biāo)志. |
defined |
與#if, #elif配合使用,判斷某個(gè)宏是否被定義 |
條件編譯功能
預(yù)處理程序提供了條件編譯的功能。條件編譯允許只編譯源文件中滿足條件的程序 段,使生成的目標(biāo)程序較短,從而減少了內(nèi)存的開銷,并提高程序的效率,可以按不同的 條件去編譯不同的程序部分,因而產(chǎn)生不同的目標(biāo)代碼文件,提高了程序的可移植性和靈活性。
應(yīng)用舉例
#undef
可以取消宏定義,與#define對(duì)應(yīng)。
#define
#define命令定義一個(gè)宏,按照是否帶參數(shù)通常分為對(duì)象宏、函數(shù)宏兩種。
對(duì)象宏
不帶參數(shù)的宏被稱為"對(duì)象宏(objectlike macro)"。對(duì)象宏多用于定義常量、通用標(biāo)識(shí)。例如:
// 常量定義
# MAX_LENGTH 100
// 通用標(biāo)識(shí),日志輸出宏
# SLog printf
// 預(yù)編譯宏
# _DEBUG
函數(shù)宏
帶參數(shù)的宏。利用宏可以提高代碼的運(yùn)行效率:子程序的調(diào)用需要壓棧出棧,這一過程如果過于頻繁會(huì)耗費(fèi)掉大量的CPU運(yùn)算資源。所以一些代碼量小但運(yùn)行頻繁的代碼如果采用帶參數(shù)宏來實(shí)現(xiàn)會(huì)提高代碼的運(yùn)行效率。但多數(shù)c++程序不推薦使用函數(shù)宏,調(diào)試上有一定難度,可考慮使用c++的inline代替之。例如:
// 最小值函數(shù)
# MIN(a,b) ((a)>(b)? (a):(b))
// 安全釋放內(nèi)存函數(shù)
#TE(p) { (NULL!=p){delete p; p = NULL;}} SAFE_DELE
defined用來測試某個(gè)宏是否被定義。defined(name): 若宏被定義,則返回1,否則返回0??捎糜谠谝粭l判斷語句中聲明多個(gè)判別條件,例如:
#ifdefined(VAX)&&defined(UNIX)&&!defined(DEBUG)
#ifdef、#ifndef、#else、#endif
#ifdef用于判斷某個(gè)宏是否定義,和#ifndef功能正好相反,二者僅支持判斷單個(gè)宏是否已經(jīng)定義。
# ABC
// ... codes while definded ABC
# (VERSION>2)
// ... codes while CODE_VERSION > 2
#
// ... remained cases
#//
//...somedeclarationcodes
#if、#elif、#else、#endif
#if可支持同時(shí)判斷多個(gè)宏的存在,與常量表達(dá)式配合使用。常用格式如下:
# 常量表達(dá)式1
// ... some codes
# 常量表達(dá)式2
// ... other codes
# 常量表達(dá)式3
// ...
...
#
// ... statement
#
常量表達(dá)式可以是包含宏、算術(shù)運(yùn)算、邏輯運(yùn)算等等的合法C常量表達(dá)式,如果常量表達(dá)式為一個(gè)未定義的宏,那么它的值被視為0。
特別注意
#if 和 #ifdef的區(qū)別
在判斷某個(gè)宏是否被定義時(shí),應(yīng)當(dāng)避免使用#if,因?yàn)樵摵甑闹悼赡芫褪潜欢x為0。而應(yīng)當(dāng)使用#ifdef或#ifndef??磧啥味未a,哪段代碼會(huì)被編譯進(jìn)去,強(qiáng)調(diào)下是編譯進(jìn)去,不是執(zhí)行。
# XXX 0
//第一段條件編譯
# XXX
邏輯1
#
邏輯2
#
# XXX0
// 第二段條件編譯
# XXX
邏輯1
#
邏輯2
#
-
第一段條件編譯:邏輯1會(huì)被編譯進(jìn)去
-
第二段條件編譯:邏輯2會(huì)被編譯進(jìn)去
區(qū)別:
#if既關(guān)心宏是否定義,又關(guān)心宏的邏輯的真假。
#ifdef(#if defined())、#ifndef(#if !defined())僅關(guān)心宏是否被定義,不關(guān)心宏的邏輯真假。
#if 0 或 #if 1注釋
當(dāng)屏蔽掉大塊代碼時(shí),使用"#if 0"比使用"/**/"要好。(因?yàn)橛?/**/"做大段的注釋時(shí),需要防止被注釋掉的代碼段中有嵌套的"/**/",一旦出現(xiàn)"/**/"嵌套"/**/"的情況,會(huì)導(dǎo)致你注釋掉的代碼區(qū)域并不是你想要的區(qū)域范圍) 。
1)常見的一種,如有一段不想要的代碼,可以直接用"#if 0 ... #endif"形式來注釋,效果等同于"/**/"
...code...
#
2)選擇結(jié)構(gòu)的條件編譯。(如果常量為真【非0,隨便什么數(shù)字,只要不是0】,就執(zhí)行程序段1,否則執(zhí)行程序段2。)
...code 1...
...code 2...
3)嵌套情況。(如果常量a為真【非0,隨便什么數(shù)字,只要不是0】,就執(zhí)行程序段1。當(dāng)常量a為0且常量b為真時(shí),執(zhí)行程序段2;當(dāng)常量a為0且常量b為0時(shí),執(zhí)行程序段3)
# constant a
...code1...
#
...code 2...
...code 3...
#
總結(jié)
有些程序在調(diào)試、兼容性、平臺(tái)移植等情況下可能想要通過簡單地設(shè)置一些參數(shù)就生成一個(gè)不同的軟件,這當(dāng)然可以通過變量設(shè)置,把所有可能用到的代碼都寫進(jìn)去,在初始化時(shí)配置,但在不同的情況下可能只用到一部分代碼,就沒必要把所有的代碼都寫進(jìn)去,就可以用條件編譯,條件編譯是為了讓程序在各種不同的軟硬件環(huán)境下都以運(yùn)行,提高其可移植性。
-
C語言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136820 -
源程序
+關(guān)注
關(guān)注
63文章
1693瀏覽量
45490 -
條件編譯
+關(guān)注
關(guān)注
0文章
3瀏覽量
5494
原文標(biāo)題:C/C++中條件編譯#if、#elif、#ifdef等靈活秒用
文章出處:【微信號(hào):gh_c472c2199c88,微信公眾號(hào):嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論