Android NDK開(kāi)發(fā)之旅8--C語(yǔ)言基礎(chǔ)--預(yù)編譯

預(yù)編譯(預(yù)處理include、define)

C語(yǔ)音的執(zhí)行流程

C語(yǔ)言執(zhí)行的流程:

  1. 編譯:形成目標(biāo)代碼(.obj)。
  2. 連接:將目標(biāo)代碼與C函數(shù)庫(kù)連接合并,形成最終的可執(zhí)行文件。
  3. 執(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

宏定義、宏替換

作用:

  1. 定義標(biāo)識(shí)。
  2. 定義常數(shù)(便于修改與閱讀)。
  3. 定義“宏函數(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):

公眾號(hào):Android開(kāi)發(fā)進(jìn)階

我的群歡迎大家進(jìn)來(lái)探討各種技術(shù)與非技術(shù)的話(huà)題,有興趣的朋友們加我私人微信huannan88,我拉你進(jìn)群交(♂)流(♀)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容