[C] 条件编译
楔子
我们在C语言训练过程中,对于编译预处理指令还是有许多人会停留在直接文本替换的宏定义阶段
但是偶尔会碰到如图红框这种未曾面熟的语句 :
那么本片博客就这一问题相关内容予以简单解析.
条件编译
来自百度百科:
—般情况下,C语言源程序中的每一行代码.都要参加编译。
但有时候出于对程序代码优化的考虑.希望只对其中一部分内容进行编译.此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译(conditional compile)。
- 条件编译的格式总共有三种:
-
#(if + 表达式) ... #else ... #endif
常量表达式非零,编译程序段1;否则编译程序段2;
#if (常量表达式)
程序段1 //常量表达式可以不加括号;
#else
程序段2
#endif
-
#(ifdef + 标识符) ... #else ... #endif
当标识符被定义过,就编译前一段程序1 ,否则编译后一段程序2.
可以理解为# if define
#ifdef (标识符)
程序段1
( #else
程序段2 )
#endif
[其中#else
部分可以省略]
-
#(ifndef + 标识符) ... #else ... #endif
当标识符未被定义过,就编译前一段程序1 ,否则编译后一段程序2
可以理解为# if not define
#ifndef (标识符)
程序段1
#else
程序段2
#endif
小结
格式2
与 格式3
的语法完全相反,可以配对记忆.
为什么明明用if
语句可以完成的功能却非要引入条件编译命令完成呢?
其实使用if
语句处理一样可以达到相同的效果,但是相比于条件编译
- 它的程序主体更加冗长,可读性不高
- 因为程序主体内所有语句都全盘执行,所以会对效率有一定影响
- 减少被编译的语句,从而减少目标的长度,当条件编译段比较多时,目标程序长度可以大大减少.感觉确实有点选择语句的意味
用途
避免重复编译
被重复引用是指一个头文件在一个.c
文件中被#include
了多次,这是由于include嵌套造成的:
- a.h文件#include “
c.h
”; - b.c文件#include “a.h” 和#include “
c.h
”;
所以造成c.h
被重复引用;
#ifndef A
#define A
… …
#endif
如果第一次未定义A,就定义A,编译代码,结束;
如果需要再次执行,已经定义完成A了,结束;
这样就避免了重复编译,提高效率
牛刀小试
#define LETTER 0
int main() {
char str[20] = "C LANGUAGE", c;
int i;
i = 0;
while ((c = str[i]) != '\0') {
i++;
#if LETTER
if (c >= 'a' && c <= 'z') {
c = c - 32;
}
#else
if (c >= 'A' && c <= 'Z') {
c = c + 32;
}
#endif
printf("%c", c);
//c language
//本题中表达式 LETTER 的值为 0
//所以编译if(c >= 'A' && c <= 'Z') c = c+32语句
//结果全部变成了小写
}
system("pause");
return 0;
}
将宏定义中常量表达式改为1
再次尝试:
#define LETTER 1
int main() {
char str[20] = "C LANGUAGE", c;
int i;
i = 0;
while ((c = str[i]) != '\0') {
i++;
#if LETTER
if (c >= 'a' && c <= 'z') {
c = c - 32;
}
#else
if (c >= 'A' && c <= 'Z') {
c = c + 32;
}
#endif
printf("%c", c);
//C LANGUAGE
//本题中表达式 LETTER 的值为 1,为'真 '
//所以编译if(c >= 'a' && c <= 'a') c = c-32语句
//结果全部变成了大写
}
system("pause");
return 0;
}
仅仅只更改了函数主体外的一个宏定义,就使条件编译指令的选择发生的改变,输出结果也因而变化,这种微妙的差异可以细细品味.