C語言程式設計藝術 條件編譯

2021-05-23 18:44:22 字數 3726 閱讀 9086

有些程式在除錯、相容性、平台移植等情況下可能想要通過簡單地設定一些引數就生成乙個不同的軟體,這當然可以通過變數設定,把所有可能用到的**都寫進去,在初始化時配置,但在不同的情況下可能只用到一部分**,就沒必要把所有的**都寫進去,就可以用條件編譯,通過預編譯指令設定編譯條件,在不同的需要時編譯不同的**。

(一)條件編譯方法

條件編譯是通過預編譯指令來實現的,主要方法有:

1、#if, #elif, #else, #endif

#if 條件 1

**段 1

#elif 條件 2

**段 2

...

#elif 條件 n

**段 n

#else

**段 n+1

#endif

即可以設定不同的條件,在編譯時編譯不同的**,預編譯指令中的表示式與c語言本身的表示式基本一至如邏輯運算、算術運算、位運算等均可以在預編譯指令中使用。之所以能夠實現條件編譯是因為預編譯指令是在編譯之前進行處理的,通過預編譯進行巨集替換、條件選擇**段,然後生成最後的待編譯**,最後進行編譯。

#if 的一般含義是如果#if 後面的常量表示式為true,則編譯它所控制的**,如條件1成立時就**段1,條件1不成立再看條件2是否成立,如果條件2成立則編譯**段2,否則再依次類推判斷其它條件,如果條件1-n都不成力則會編譯最後的**段n+1。

2、#ifdef, #else, #endif或#ifndef, #else, #endif

條件編譯的另一種方法是用#ifdef與#ifndef命令,它們分別表示「如果有定義」及「如果無定義」。有定義是指在編譯此段**時是否有某個巨集通過 #define 指令定義的巨集,#ifndef指令指找不到通過 #define 定義的某巨集,該巨集可以是在當前檔案此條指令的關面定義的,也可以是在其它檔案中,但在此指令之前包含到該檔案中的。

#ifdef的一般形式是:

#ifdef macro_name

**段 1

#else

**段 2

#endif

或 #ifdef的一般形式是:

#ifndef macro_name

**段 2

#else

**段 1

#endif

這兩段**的效果是完全一樣的。

3、通過巨集函式defined(macro_name)

引數為巨集名(無需加""),如果該macro_name定義過則返回真,否則返回假,用該函式則可以寫比較複雜的條件編譯指令如

#if defined(macro1) || (!defined(macro2) && defined(macro3))

...#else

...#endif

(二)條件編譯技巧與示例

(1)#ifdef和#defined()比較

首先比較一下這兩種方法,第一種方法只能判斷乙個巨集,如果條件比較複雜實現起來比較煩鎖,用後者就比較方便。如有兩個巨集macro_1,macro_2只有兩個巨集都定義過才會編譯**段a,分別實現如下:

#ifdef macro_1

#ifdef macro_2

**段 a

#endif

#endif

或者

#if defined(macro_1) && defined(macro_2)

#endif

同樣,要實現更複雜的條件用#ifdef更麻煩,所以推薦使用後者,因為即使當前**用的是簡單的條件編譯,以後在維護、公升級時可能會增加,用後者可維護性較強。舊的編譯器可能沒有實現#defined()指令,c99已經加為標準。要相容老的編譯器,還需用#ifdef指令。

2、#if與 #ifdef或#if defined()比較

比如自己寫了乙個printf函式,想通過乙個巨集my_printf_en實現條件編譯,用#if可實現如下

#define my_printf_en 1

#if mys_printf_en == 1

int printf(char* fmt, char* args, ...)

#endif

如果巨集my_printf_en定義為1則編譯這段**,如果巨集定義不為1或者沒有定義該巨集,則不編譯這段**。同樣也可以通過#ifdef或者#defined()實現,如

#define my_printf_en 1

#if defined(my_printf_en)

int printf(char* fmt, char* args, ...)

#elif my_printf_version == 3

int printf(unsigned char com_number, char* str)

#endif

這種情況下還得用到#ifdef或#if defined(),你可以不用動主體的任何**,只需要修改printf.c檔案中my_rpintf_version巨集的數字就可以改變了,如果用前面那種方法還得拖動**,在拖動中就有可能造成錯誤。

再試想,如果軟體公升級了,或者有了大的改動,原來有三個版本,現在只剩下兩個版本了,如

#if my_printf_version == 2

int printf(char* fmt, char* args, ...)

#elif my_printf_version == 3

int printf(unsigned char com_number, char* str)

#endif

因為這些核心**不想讓使用這些**的人關心,他們只需要修改config.h檔案,那就要在printf.c中實現相容性。如果以前有人在config.h配置巨集my_printf_version為1,即有

#define my_printf_version   1

而現在沒有1版本了,要想相容怎麼辦?那當然可以用更複雜的條件實現如:

#if my_printf_version == 2 || my_printf_version == 1

int printf(char* fmt, char* args, ...)

#elif my_printf_version == 3

int printf(unsigned char com_number, char* str)

#endif

不過還有另外一種方法,即使用#undef命令

#if my_printf_version == 1

#undef my_printf_version

#define my_printf_version  2

#endif

#if my_printf_version == 2

int printf(char* fmt, char* args, ...)

#elif my_printf_version == 3

int printf(unsigned char com_number, char* str)

#endif

用#if還有乙個好處,如果你把巨集名記錯了,把my_printf_en定義成了my_print_en,那麼你用#ifdef my_printf_en或者#if defined(my_printf_en)控制的**就不能被編譯,查起來又不好查,用#if my_printf_en ==1控制就很好查,因為你把my_printf_en定義成my_print_en,則my_printf_en實際上沒有定義,那麼編譯器會給出警告#if my_printf_en == 1中的my_printf_en沒有定義,但錯就比較快。

C語言程式設計藝術 條件編譯

有些程式在除錯 相容性 平台移植等情況下可能想要通過簡單地設定一些引數就生成乙個不同的軟體,這當然可以通過變數設定,把所有可能用到的 都寫進去,在初始化時配置,但在不同的情況下可能只用到一部分 就沒必要把所有的 都寫進去,就可以用條件編譯,通過預編譯指令設定編譯條件,在不同的需要時編譯不同的 一 條...

C語言程式設計 之 條件編譯 備忘

條件編譯常用的有 if,ifdef,ifndef等。本部落格記錄一下,如何根據某個引數值的不同,選擇不同的分支來編譯。使用 if elif elif else endif 直接附上democode 架構,如下 define your choice 2 if 0 your choice 此處寫出你想要...

C語言的條件編譯

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