C語言中的條件編譯

2021-10-02 11:31:41 字數 3251 閱讀 1899

很久沒更新了。。。因為工作之後比較忙,更多的學習記錄會寫在公司的wiki裡

目前在公司主要做c/c++,原來了解不夠深入,所以目前從基礎開始簡單記錄一點東西。

條件編譯相關的預編譯指令,包括  #define、#undef、#ifdef、#ifndef、#if、#elif、#else、#endif、defined。

#define            定義乙個預處理巨集

#undef            取消巨集的定義

#if                   編譯預處理中的條件命令,相當於c語法中的if語句

#ifdef              判斷某個巨集是否被定義,若已定義,執行隨後的語句

#ifndef            與#ifdef相反,判斷某個巨集是否未被定義

#elif                若#if, #ifdef, #ifndef或前面的#elif條件不滿足,則執行#elif之後的語句,相當於c語法中的else-if

#else              與#if, #ifdef, #ifndef對應, 若這些條件不滿足,則執行#else之後的語句,相當於c語法中的else

#endif             #if, #ifdef, #ifndef這些條件命令的結束標誌.

defined          與#if, #elif配合使用,判斷某個巨集是否被定義

條件編譯是根據實際定義巨集(某類條件)進行**靜態編譯的手段。可根據表示式的值或某個特定巨集是否被定義來確定編譯條件。最常見的條件編譯是防止重複包含標頭檔案的巨集:

1 #ifndef abcd_h

2 #define abcd_h

3 4 // ... some declaration codes

5 6 #endif // #ifndef abcd_h

這種場景使用最多。一般規範的編碼習慣都會這樣做。

#if system == sysv

#define hdr "sysv.h"

#elif system == bsd

#define hdr "bsd.h"

#elif system == msdos

#define hdr "msdos.h"

#else

#define hdr "default.h"

#endif

#include hdr

其中#ifdef #ifundef後面加符號(巨集定義)。

0 恆 false,1 恆true。

在c語言中時常會用到#if 0,#if 1,#else,#endif語句,語句如下所示:

#if 0

code1

#else

code2

#endif

此時code1的語句被注釋掉了,永遠沒有辦法執行,而code2是被編譯的;如果將#if 0變為#if 1,code1被編譯,而code2永遠沒有辦法被執行。

如果是c++調c庫,例如有了乙個c庫檔案,它的標頭檔案是f.h

extern "c"

其中,extern "c" {}告訴編譯器用c的規則去呼叫c函式。這裡是在include標頭檔案的外面包裹了extern "c" ,是告訴編譯器以c語言的命名方式去載入這個符號。還有一種比較常見的方式是在標頭檔案中進行編譯宣告,如下所示,這樣的話,無論c還是c++直接正常include就可以使用了。

cadd.h

#ifdef __cplusplus

extern "c"

#endif

如上使用 __cplusplus巨集的方法可以保證,這段程式既可以在c 中被編譯,要可以在c++中被編譯。

具體原因:

由於cpp支援多型性,也就是具有相同函式名的函式可以完成不同的功能,cpp通常是通過引數區分具體呼叫的是哪乙個函式。在編譯的時候,cpp編譯器會將引數型別和函式名連線在一起,於是在程式編譯成為目標檔案以後,cpp編譯器可以直接根據目標檔案中的符號名將多個目標檔案連線成乙個目標檔案或者可執行檔案。但是在c語言中,由於完全沒有多型性的概念,c編譯器在編譯時除了會在函式名前面新增乙個下劃線之外,什麼也不會做(至少很多編譯器都是這樣幹的)。由於這種的原因,當採用cpp與c混合程式設計的時候,就可能會出問題。

要明白為何使用extern"c",還得從cpp中對函式的過載處理開始說起。在c++中,為了支援過載機制,在編譯生成的彙編碼中,要對函式的名字進行一些處理,加入比如函式的返回型別等等.而在c中,只是簡單的函式名字而已,不會加入其他的資訊.也就是說:c++和c對產生的函式名字的處理是不一樣的.

extern關鍵字,對該變數作「外部變數宣告」,以擴充套件全域性變數的作用域。

謹記:宣告可以多次,但是定義只能有一次。函式的宣告extern關鍵字是可有可無的,因為函式本身不加修飾的話就是extern的。

由於用 extern 引用外部變數,可以在引用的模組內修改其變數的值,因此,如果有多個檔案同時要對應用的變數進行操作,而且可能會修改該變數,那就會影響其他模組的使用。因此,我們要慎重使用。

(1) 變數 

extern int a; //宣告乙個全域性變數

int a; //定義乙個全域性變數

extern int a = 0;//定義全域性變數並給初值

int a = 0; //定義全域性變數並給初值

上面的四個只有第乙個extern int a才是宣告,其他的全是定義。 當你要引用乙個全域性變數時,你就要宣告extern int a;這個時候extern不能省,否則就成定義了。

(2) 函式 

函式也有宣告和定義,但由於函式的宣告和定義是有區別的,函式的定義是有函式體的,所以函式的宣告和定義都可以將extern省略掉,反正其他檔案也是知道這個函式是在其他地方定義的。

#include int max(int x,int y);

int main(void)

/*定義兩個全域性變數*/

int g_x = 10;

int g_y = 20;

int max(int x, int y)

C語言中的條件編譯

條件編譯的功能使得我們可以按不同的條件去編譯不同的程式部分,因而產生不同的目 標 檔案。這對於程式的移植和除錯是很有用的。條件編譯有三種形式,下面分別介紹 第一種形式 ifdef 識別符號 程式段 1 else 程式段 2 endif 它的功能是,如果識別符號已被 define 命令定義過則對程式段...

c語言中的條件編譯

即意味著編譯預處理 define debug 是一種沒具體定義值的預定義 僅僅是定義過 用在條件編譯中如標頭檔案中 ifndef debug define debug endif 2.int i 是變數的定義 extern int i 是變數的宣告 宣告不產生 如函式原型 變數宣告 結構宣告 巨集宣...

C語言中的條件編譯

常用的預編譯指令包括檔案包含,巨集定義和條件編譯 檔案包含 檔案包含很簡單,也是最常見的,語法格式 include 標頭檔案 include 標頭檔案 順便說一下這兩種形式的不同 尖括號 這種方法只能引用編譯器類裡的標頭檔案 也就是編譯器只會查詢儲存系統標準標頭檔案的檔案 雙引號 這種方法編譯器先查...