如何提高代碼逼格?宏定義-從入門到放棄
一、前言
二、預(yù)處理器的操作
三、宏擴(kuò)展
四、符號(hào):# 與 ##
五、可變參數(shù)的處理
六、奇思妙想的宏
七、總結(jié)
一、前言
一直以來(lái),我都有這樣一種感覺(jué):當(dāng)我學(xué)習(xí)一個(gè)新領(lǐng)域的知識(shí)時(shí),如果其中的某個(gè)知識(shí)點(diǎn)在剛開始接觸時(shí),我感覺(jué)比較難懂、不好理解,那么以后不論我花多長(zhǎng)時(shí)間去研究這個(gè)知識(shí)點(diǎn),心里會(huì)一直認(rèn)為該知識(shí)點(diǎn)比較難,也就是說(shuō)第一印象特別的重要。
就比如 C 語(yǔ)言中的宏定義,好像跟我犯沖一樣,我一直覺(jué)得宏定義是 C 語(yǔ)言中最難的部分,就好比有有些小伙伴一直覺(jué)得指針是 C 語(yǔ)言中最難的部分一樣。
宏的本質(zhì)就是代碼生成器,在預(yù)處理器的支持下實(shí)現(xiàn)代碼的動(dòng)態(tài)生成,具體的操作通過(guò)條件編譯和宏擴(kuò)展來(lái)實(shí)現(xiàn)。我們先在心中建立這么一個(gè)基本的概念,然后通過(guò)實(shí)際的描述和代碼來(lái)深入的體會(huì):如何駕馭宏定義。
所以,今天我們就來(lái)把宏定義所有的知識(shí)點(diǎn)進(jìn)行匯總、深挖,希望經(jīng)過(guò)這篇文章,我能夠擺脫心理的這個(gè)魔障?赐赀@篇總結(jié)文章后,我相信你也一定能夠?qū)甓x有一個(gè)總體、全局的把握。
二、預(yù)處理器的操作
1. 宏的生效環(huán)節(jié):預(yù)處理
一個(gè) C 程序在編譯的時(shí)候,從源文件開始到最后生成二進(jìn)制可執(zhí)行文件,一共經(jīng)歷 4 個(gè)階段:
我們今天討論的內(nèi)容就是在第一個(gè)環(huán)節(jié):預(yù)處理,由預(yù)處理器來(lái)完成這個(gè)階段的工作,包括下面這 4 項(xiàng)工作:
文件引入(#include);條件編譯(#if..#elif..#endif);宏擴(kuò)展(macro expansions);行控制(line control)。2. 條件編譯
一般情況下,C 語(yǔ)言文件中的每一行代碼都是要被編譯的,但是有時(shí)候出于對(duì)程序代碼優(yōu)化的考慮,希望只對(duì)其中的一部分代碼進(jìn)行編譯,此時(shí)就需要在程序中加上條件,讓編譯器只對(duì)滿足條件的代碼進(jìn)行編譯,將不滿足條件的代碼舍棄,這就是條件編譯。
簡(jiǎn)單的說(shuō):就是預(yù)處理器根據(jù)我們?cè)O(shè)置的條件,對(duì)代碼進(jìn)行動(dòng)態(tài)的處理,把有效的代碼輸出到一個(gè)中間文件,然后送給編譯器進(jìn)行編譯。
條件編譯基本上在所有的項(xiàng)目代碼中都被使用到,例如:當(dāng)你需要考慮下面的幾種情況時(shí),就一定會(huì)使用條件編譯:
需要把程序編譯成不同平臺(tái)下的可執(zhí)行程序;同一套代碼需要運(yùn)行在同一平臺(tái)上的不同功能產(chǎn)品上;在程序中存在著一些測(cè)試目的的代碼,不想污染產(chǎn)品級(jí)的代碼,需要屏蔽掉。
這里舉 3 個(gè)例子,在代碼中經(jīng)?吹降年P(guān)于條件編譯:
示例1:用來(lái)區(qū)分 C 和 C++ 代碼
#ifdef __cplusplus extern "C" { #endif void hello(); #ifdef __cplusplus } #endif
這樣的代碼幾乎在每個(gè)開源庫(kù)中都可能見到,主要的目的就是 C 和 C++ 混合編程,具體來(lái)說(shuō)就是:
如果使用 gcc 來(lái)編譯,那么宏 __cplusplus 將不存在,其中的 extern "C" 將會(huì)被忽略;如果使用 g++ 來(lái)編譯,那么宏 __cplusplus 就存在,其中的 extern "C" 就發(fā)生作用,編譯出來(lái)的函數(shù)名 hello 就不會(huì)被 g++ 編譯器改寫,因此就可以被 C 代碼來(lái)調(diào)用;
示例2:用來(lái)區(qū)分不同的平臺(tái)
#if defined(linux) || defined(__linux) || defined(__linux__) sleep(1000 * 1000); // 調(diào)用 Linux 平臺(tái)下的庫(kù)函數(shù)#elif defined(WIN32) || defined(_WIN32) Sleep(1000 * 1000); // 調(diào)用 Windows 平臺(tái)下的庫(kù)函數(shù)(第一個(gè)字母是大寫)#endif
那么,這些 linux, __linux, __linux__, WIN32, _WIN32 是從哪里來(lái)的呢?我們可以認(rèn)為是編譯目標(biāo)平臺(tái)(操作系統(tǒng))為我們預(yù)先準(zhǔn)備好的。
示例3:在編寫 Windows 平臺(tái)下的動(dòng)態(tài)庫(kù)時(shí),聲明導(dǎo)出和導(dǎo)入函數(shù)
#if defined(linux) || defined(__linux) || defined(__linux__) #define LIBA_API #else #ifdef LIBA_STATIC #define LIBA_API #else #ifdef LIBA_API_EXPORTS #define LIBA_API __declspec(dllexport) #else #define LIBA_API __declspec(dllimport) #endif #endif#endif
// 函數(shù)聲明LIBA_API void hello();
這段代碼是直接從我之前在 B 站錄制的一個(gè)小視頻里的示例拿過(guò)來(lái)的,當(dāng)時(shí)主要是演示如何如何在 Linux 平臺(tái)下使用 make 和 cmake 構(gòu)建工具來(lái)編譯,后來(lái)又小伙伴讓我在 Windows 平臺(tái)下也用 make 和 cmake 來(lái)構(gòu)建,所以就寫了上面這段宏定義。
在使用 MSVC 編譯動(dòng)態(tài)庫(kù)時(shí),需要在編譯選項(xiàng)(Makefle 或者 CMakeLists.txt)中定義宏 LIBA_API_EXPORTS,那么導(dǎo)出函數(shù) hello 的最前面的宏 LIBA_API 就會(huì)被替換成:__declspec(dllexport),表示導(dǎo)出操作;在編譯應(yīng)用程序的時(shí)候,使用動(dòng)態(tài)庫(kù),需要 include 動(dòng)態(tài)庫(kù)的頭文件,此時(shí)在編譯選項(xiàng)中不需要定義宏 LIBA_API_EXPORTS,那么 hello 函數(shù)最前面的 LIBA_API 就會(huì)被替換成 __declspec(dllimport),表示導(dǎo)入操作;補(bǔ)充一點(diǎn):如果使用靜態(tài)庫(kù),編譯選項(xiàng)中不需要任何宏定義,那么宏 LIBA_API 就為空。3. 平臺(tái)預(yù)定義的宏
上面已經(jīng)看到了,目標(biāo)平臺(tái)會(huì)為我們預(yù)先定義好一些宏,方便我們?cè)诔绦蛑惺褂谩3松厦娴牟僮飨到y(tǒng)相關(guān)宏,還有另一類宏定義,在日志系統(tǒng)中被廣泛的使用:
FILE:當(dāng)前源代碼文件名;
LINE:當(dāng)前源代碼的行號(hào);
FUNCTION:當(dāng)前執(zhí)行的函數(shù)名;
DATE:編譯日期;
TIME:編譯時(shí)間;
例如:
printf("file name: %s, function name = %s, current line:%d ", __FILE__, __FUNCTION__, __LINE__);

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
您提交的評(píng)論過(guò)于頻繁,請(qǐng)輸入驗(yàn)證碼繼續(xù)
圖片新聞
-
機(jī)器人奧運(yùn)會(huì)戰(zhàn)報(bào):宇樹機(jī)器人摘下首金,天工Ultra搶走首位“百米飛人”
-
存儲(chǔ)圈掐架!江波龍起訴佰維,索賠121萬(wàn)
-
長(zhǎng)安汽車母公司突然更名:從“中國(guó)長(zhǎng)安”到“辰致科技”
-
豆包前負(fù)責(zé)人喬木出軌BP后續(xù):均被辭退
-
字節(jié)AI Lab負(fù)責(zé)人李航卸任后返聘,Seed進(jìn)入調(diào)整期
-
員工持股爆雷?廣汽埃安緊急回應(yīng)
-
中國(guó)“智造”背后的「關(guān)鍵力量」
-
小米汽車研發(fā)中心重磅落地,寶馬家門口“搶人”
最新活動(dòng)更多
-
10月23日火熱報(bào)名中>> 2025是德科技創(chuàng)新技術(shù)峰會(huì)
-
10月23日立即報(bào)名>> Works With 開發(fā)者大會(huì)深圳站
-
10月24日立即參評(píng)>> 【評(píng)選】維科杯·OFweek 2025(第十屆)物聯(lián)網(wǎng)行業(yè)年度評(píng)選
-
11月27日立即報(bào)名>> 【工程師系列】汽車電子技術(shù)在線大會(huì)
-
12月18日立即報(bào)名>> 【線下會(huì)議】OFweek 2025(第十屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會(huì)
-
精彩回顧立即查看>> 【限時(shí)福利】TE 2025國(guó)際物聯(lián)網(wǎng)展·深圳站
推薦專題
- 1 人形機(jī)器人,正狂奔在批量交付的曠野
- 2 宇樹機(jī)器人撞人事件的深度剖析:六維力傳感器如何成為人機(jī)安全的關(guān)鍵屏障
- 3 解碼特斯拉新AI芯片戰(zhàn)略 :從Dojo到AI5和AI6推理引擎
- 4 AI版“四萬(wàn)億刺激”計(jì)劃來(lái)了
- 5 2025年8月人工智能投融資觀察
- 6 7 a16z最新AI百?gòu)?qiáng)榜:硅谷頂級(jí)VC帶你讀懂全球生成式AI賽道最新趨勢(shì)
- 8 Manus跑路,大廠掉線,只能靠DeepSeek了
- 9 一家被嚴(yán)重低估的國(guó)產(chǎn)AI巨頭
- 10 地平線的野心:1000萬(wàn)套HSD上車