预备知识:
- 预处理也称为预编译,它为编译做准备工作,主要进行代码文本的替换工作,用于处理#开头的指令,其中预处理产生编译器的输出
。 参考地址:预处理与编译
- 程序的整体过程为:预处理 --》 编译 --》 运行
。
在C语言中有一种机制可以决定编译哪些代码,这个机制就是预处理中的条件编译。本篇主要介绍常用的判断语句。
总结如下:
1.判断语句条件编译#if…#endif的使用
2.是否被定义:
- #if预处理和defined,!defined预处理相结合的方式
- 使用简写的#ifdef和#ifndef的形式
3.多重判断#if…#elif…#else…#endif
4. .h文件中条件编译语句的含义
使用条件编译,你可以选择代码的一部分是否被正常编译,C中条件编译的主要形式有三种。
1.判断语句条件编译#if...#endif
常用形式如下:
#if 常量表达式
执行语句
#endif
其中的常量表达式是由预处理器进行求值,
预处理器进行求值的方法:这一句之前define 常量表达式 1或者在#if 常量表达式中将常量表达式写作0或者1
如果常量表达式的值是非零值(真),那么执行语句就会参与到代码的编译中来。否则,预处理器就会忽略,不参与编译。
有以下代码:
#include <iostream>
#define DEBUG1 0
#define DEBUG2 1
int main(int argc, char* argv[])
{
#if DEBUG1
printf("Enter debug1 mode\n");
#endif
#if DEBUG2
printf("Enter debug2 mode\n");
#endif
return 0;
}
运行结果:由于DEBUG2
为非0
,输出Enter debug2 mode
实际上在编译器生成中间文件时,因为DEBUG2=0
将其对应的#ifdef DEBUG2
部分不会编译,中间文件中就只剩下面内容:
int main(int argc, char* argv[])
{
#if DEBUG2
printf("Enter debug2 mode\n");
#endif
return 0;
}
1.1 判断语句条件编译与程序语句的区别
上面的语句也可以使用程序语句:if( ) { }
实现,有什么区别呢?
宏和程序语句完成相应功能的区别在于: 程序语句都会被包含在编译的中间文件中,条件编译就根据条件决定是否被编译
。
条件编译在编译前,文本处理上就可以根据条件判断是否包含相应的文本,生成的代码就可以又可靠,空间又小
if( ) { }
不管怎样都会被包含进去,占用程序空间和时间
2.是否被定义
C语言程序中,“是否被定义”是使用最频繁的,实现是否被定义主要有2种方式。
2.1 使用#if预处理和defined,!defined预处理相结合的方式
一种是使用#if预处理和defined,!defined预处理相结合的方式。
defined为具体判断符号x是否被定义,一旦这个符号x被定义之后,使用defined(x),其最终结果会返回一个1,使用!defined(x),其最终结果会返回一个0,最终#if 会根据返回值来选择代码是否要被编译。
其使用形式为:
#if defined (符号)
程序语句
#endif
#if !defined (符号)
程序语句
#endif
下例中,我们要判断DEBUG
是否被定义,一旦被定义之后,就输出“In debug mode”
。如果DEBUG没有被定义,那么就定义RELEASE
,如果RELEASE被定义,那么就输出“In release mode”
。
具体代码如下:
#include <iostream>
#define DEBUG
int main(int argc, char* argv[])
{
#if defined(DEBUG)
printf("In debug mode\n");
#endif
#if !defined(DEBUG)
#define RELEASE
#endif
#if defined(RELEASE)
printf("In release mode\n");
#endif
return 0;
}
运行结果:
将代码中#define DEBUG
注释之后,就会输出“In release mode”
#include <iostream>
//#define DEBUG
int main(int argc, char* argv[])
{
#if defined(DEBUG)
printf("In debug mode\n");
#endif
#if !defined(DEBUG)
#define RELEASE
#endif
#if defined(RELEASE)
printf("In release mode\n");
#endif
return 0;
}
运行结果:
2.2 使用简写的#ifdef和#ifndef的形式
第二种方式,可以使用简写的#ifdef和#ifndef的形式来完成这个功能
#if defined(符号)<-->#ifdef 符号
#if !defined(符号)<-->#ifndef 符号
对于上面的代码就可以使用#ifdef和#ifndef的形式进行替换
#include <iostream>
#define DEBUG
int main(int argc, char* argv[])
{
#ifdef DEBUG
printf("In debug mode\n");
#endif
#ifndef DEBUG
#define RELEASE
#endif
#ifdef RELEASE
printf("In release mode\n");
#endif
return 0;
}
运行结果:
3.多重判断
除了以上进行一次判断,C中还提供了多重判断的形式,这种使用相对较少,以下为实例:
#include <iostream>
#define MODE1 1
#define MODE2 0
#define MODE3 0
int main(int argc, char* argv[])
{
#if MODE1
printf("mode1");
#elif MODE2
printf("mode2");
#else
printf("mode3");
#endif
return 0;
}
运行结果:
4..h中条件编译语句的含义
通常我们的.h文件中,都会有形如以下的三行代码:
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
......
#endif // MAINWIDGET_H
假设a.h
文件要同时被1.c
,2.c
,3.c
包含,a.h
中有一个变量int a
,int a就会被定义3次,这肯定是不行的。
通过上面的三行代码可以实现a.h
中的MAINWIDGET_H
标号只会被包含一次定义一次,当预处理器再去处理被包含在其他.c
文件时,由于MAINWIDGET_H
标号被二次定义,所以#define MAINWIDGET_H ...... #endif // MAINWIDGET_H
中间的内容为灰色不被包含,此时a.h
只在1.c
被定义和包含,被编译器注册过后,1.c
,2.c
,3.c
都可以识别使用a.h的内容。
因此才有了以上的三句,一般保证MAINWIDGET_H
标号是唯一的,可以写作其他形式_MAINWIDGET_H
…都是可以的。
5.学习视频地址:条件编译(上)——判断语句条件编译,条件编译(下)——符号是否被定义