預(yù)編譯(預(yù)處理include、define)
C語(yǔ)音的執(zhí)行流程
C語(yǔ)言執(zhí)行的流程:
- 編譯:形成目標(biāo)代碼(.obj)。
- 連接:將目標(biāo)代碼與C函數(shù)庫(kù)連接合并,形成最終的可執(zhí)行文件。
- 執(zhí)行。
預(yù)編譯(預(yù)處理),為編譯做準(zhǔn)備工作,完成代碼文本的替換工作。
頭文件告訴編譯器有這樣一個(gè)函數(shù),連接器負(fù)責(zé)找到這個(gè)函數(shù)的實(shí)現(xiàn),通過(guò)include引入。實(shí)現(xiàn)的話(huà),在哪里都可以。類(lèi)似于Android布局文件中的include標(biāo)簽。
一個(gè)簡(jiǎn)單的例子:
創(chuàng)建text.txt文件:
printf("我被包含進(jìn)來(lái)了");
在主函數(shù)里面使用:
#include<stdio.h>
#include<stdlib.h>
void main(){
#include "text.txt"
system("pause");
}
實(shí)質(zhì)上會(huì)把include標(biāo)簽替換成我們自己的text.txt文件里面的內(nèi)容。
VS源碼的目錄:C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\crt\src
宏定義、宏替換
作用:
- 定義標(biāo)識(shí)。
- 定義常數(shù)(便于修改與閱讀)。
- 定義“宏函數(shù)”。
1、定義標(biāo)識(shí)
作用:
1、例如通過(guò)判斷一些標(biāo)識(shí)是否定義來(lái)判斷是否支持某種語(yǔ)法、平臺(tái)等等:
//表示支持C++語(yǔ)法
#ifdef __cplusplus
#endif // __cplusplus
//表示支持Android、Windows、蘋(píng)果平臺(tái)等等
#ifdef ANDROID
#endif // ANDROID
2、防止問(wèn)價(jià)你重復(fù)引入:
舉個(gè)例子,我們有三個(gè)文件a.h、b.h、Test.cpp,分別如下:
這是a.h:
#include "b.h"
void a();
這是b.h:
#include "a.h"
void b();
最后Test.cpp里面引用了a.h
#include "a.h"
這樣,當(dāng)Test包含a的時(shí)候,a又會(huì)去包含b,b又會(huì)包含a,這樣就會(huì)造成循環(huán)包含。類(lèi)似于Hibernate里面的SQL循環(huán)引用。最終會(huì)報(bào)如下錯(cuò)誤:
fatal error C1014: 包含文件太多 : 深度 = 1024
通過(guò)宏定義判斷就可以解決這個(gè)問(wèn)題:(b.h省略)
#if A_H
#include "b.h"
void a();
#endif
另外,新版本的時(shí)候通過(guò)#pragma once語(yǔ)句即可自動(dòng)解決這個(gè)問(wèn)題。
//該頭文件只被包含一次,編譯器自動(dòng)處理循環(huán)包含問(wèn)題
#pragma once
2、定義常熟,方便閱讀
一個(gè)簡(jiǎn)單的例子:
#define MAX 100
void main(){
int i = 100;
if (i == MAX){
printf("哈哈");
}
system("pause");
}
3、定義“宏函數(shù)”。
實(shí)質(zhì)上就是一個(gè)替換的過(guò)程。
簡(jiǎn)單實(shí)用例子:
#define LOG(FORMAT , ...) printf("info"); printf(##FORMAT , __VA_ARGS__);
LOG會(huì)有級(jí)別,于是進(jìn)一步升級(jí):
#define LOG_I(FORMAT , ...) printf("info"); printf(##FORMAT , __VA_ARGS__);
#define LOG_E(FORMAT , ...) printf("error"); printf(##FORMAT , __VA_ARGS__);
進(jìn)一步簡(jiǎn)化重復(fù)代碼,重復(fù)LEVEL日志級(jí)別:
#define LOG(LEVEL , FORMAT , ...) printf(##LEVEL); printf(##FORMAT , __VA_ARGS__);
#define LOG_I(FORMAT , ...) LOG("info" , ##FORMAT , __VA_ARGS__)
#define LOG_E(FORMAT , ...) LOG("error" , ##FORMAT , __VA_ARGS__)
在Android JNI開(kāi)發(fā)的時(shí)候,我們打印一句日志是通過(guò)__android_log_print函數(shù)來(lái)實(shí)現(xiàn)的,因此我們可以通過(guò)宏定義簡(jiǎn)化代碼:
#define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,"jason",FORMAT,##__VA_ARGS__);
LOGI("%s","fix");
//替換
__android_log_print(ANDROID_LOG_INFO, "jason", "%s", "fix");
如果覺(jué)得我的文字對(duì)你有所幫助的話(huà),歡迎關(guān)注我的公眾號(hào):
我的群歡迎大家進(jìn)來(lái)探討各種技術(shù)與非技術(shù)的話(huà)題,有興趣的朋友們加我私人微信huannan88,我拉你進(jìn)群交(♂)流(♀)。