C语言的条件编译
当前位置:以往代写 > C/C++ 教程 >C语言的条件编译
2019-06-13

C语言的条件编译

C语言的条件编译

副标题#e#

有些措施在调试、兼容性、平台移植等环境下大概想要通过简朴地配置一些参数就生成一个差异的软件,这虽然可以通过变量配置,把所有大概用到的代码都写进去,在初始化时设置,但在差异的环境下大概只用到一部门代码,就没须要把所有的代码都写进去,就可以用条件编译,通过预编译指令配置编译条件,在差异的需要时编译差异的代码。

(一)条件编译要领

条件编译是通过预编译指令来实现的,主要要领有:

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, ...)
{
...
}
#endif


#p#副标题#e#

在这种环境下两种要领具有异曲同工之妙,但试想假如你为了节省代码写了两个printf函数,在差异环境下利用差异的printf函数,一个是精简版一个是全成果尺度版,如:

#define MY_PRINTF_SIMPLE

#ifdef MY_PRINTF_SIMPLE
void printf(*str) // 向终端简朴地输出一个字符串
{...
}
#endif
#ifdef MY_PRINTF_STANDARD
int printf(char* fmt, char* args, ...)
{...
}
#endif

同样可以用#if defined()实现
#define MY_PRINTF_SIMPLE

#if defined(MY_PRINTF_SIMPLE)
void printf(*str) // 向终端简朴地输出一个字符串
{
...
}
#elif defined(MY_PRINTF_STANDARD)
int printf(char* fmt, char* args, ...)
{
...
}
#endif

#p#分页标题#e#

两种要领都可以实现,但可见后者更利便。但试想假如你有三个版本,用前者就更贫苦了,但要领相似,用后者就更利便,但仍需三个宏举办节制,你要住三个宏,改造一下就用#if可以用一个宏直接节制N种环境如:

#define MY_PRINTF_VERSION     1

#if MY_PRINTF_VERSION == 1
void printf(*str) // 向终端简朴地输出一个字符串
{
...
}
#elif MY_PRINTF_VERSION == 2
int printf(char* fmt, char* args, ...)
{
...
}
#elif MY_PRINTF_VERSION == 3
int printf(unsigned char com_number, char* str)
{
...
}
#else
默认版本
#endif

这样,你只需修改一下数字就可以完成版本的选择了

看来仿佛用#if 较量好了,试想如下环境:你写了一个设置文件叫做config.h用来设置一些宏,通过这些宏来节制代码,如你在config.h的宏

#define MY_PRINTF_EN 1

来节制是否需要编译本身的printf函数,而在你的源代码文件printf.c中有如下指令

#i nclude "config.h"
#if MY_PRINTF_EN == 1
int printf(char* fmt, char* args, ...)
{
...
}
#endif

但这样也会有一个问题,就是假如你忘了在config.h中添加宏MY_PRINTF_EN,那么本身写的printf函数也不会被编译,有些编译器会给出告诫:MY_PRINTF_EN未界说。假如你有两个版本的想有一个默认版本,可以在printf.c中这样实现

#incldue "config.h"
#if !defined(MY_PRINTF_VERSION)
#define MY_PRINTF_VERSION   1
#endif

#if MY_PRINTF_VERSION == 1
void printf(*str) // 向终端简朴地输出一个字符串
{
...
}
#elif MY_PRINTF_VERSION == 2
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

#p#副标题#e#

因为这些焦点代码不想让利用这些代码的人体贴,他们只需要修改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没有界说,但错就较量快。

    关键字:

在线提交作业