预处理器是一个在用C语言编程时对我们帮助很大的工具,它是C标准的一部分,就像语言、编译器和标准库一样。
它解析我们的程序,确保编译器在继续工作之前获得所有需要的东西。
在实践中,它做了什么?
例如,它查找你用#include 指令包含的所有头文件。
它还会查看你用#define 定义的每一个常量,并用它的实际值进行替换。
这只是一个开始,我提到这两个操作是因为它们是最常见的。预处理器可以做的事情还有很多。
你是否注意到#include 和#define 在开头有一个# ?那是所有预处理器指令的共同点。如果某一行以# 开始,预处理器就会处理这个问题。
条件式
我们可以做的一件事是使用条件语句来改变我们的程序的编译方式,这取决于一个表达式的值。
例如,我们可以检查DEBUG 常数是否为0。
#include <stdio.h>
const int DEBUG = 0;
int main(void) {
#if DEBUG == 0
printf("I am NOT debugging\n");
#else
printf("I am debugging\n");
#endif
}
符号常量
我们可以定义一个符号常量。
#define VALUE 1
#define PI 3.14
#define NAME "Flavio"
当我们在程序中使用NAME或PI或VALUE时,在执行程序前,预处理器会将其名称替换为数值。
符号常量非常有用,因为我们可以给数值命名,而不需要在编译时创建变量。
宏
通过#define ,我们也可以定义一个宏。宏和符号常量之间的区别是,宏可以接受一个参数,通常包含代码,而符号常量是一个值。
#define POWER(x) ((x) * (x))
注意参数周围的圆括号,这是一个很好的做法,可以避免在预编译过程中替换宏的问题。
然后我们可以在我们的代码中这样使用它。
printf("%u\n", POWER(4)); //16
与函数最大的区别是,宏不指定其参数或返回值的类型,这在某些情况下可能很方便。
如果定义了
我们可以用#ifdef 来检查一个符号常量或宏是否被定义。
#include <stdio.h>
#define VALUE 1
int main(void) {
#ifdef VALUE
printf("Value is defined\n");
#else
printf("Value is not defined\n");
#endif
}
我们也有#ifndef 来检查相反的情况(宏未定义)。
我们还可以使用#if defined 和#if !defined 来完成同样的任务。
将一些代码块包裹在这样一个块中是很常见的。
来暂时阻止它的运行,或者使用一个DEBUG符号常量。
#define DEBUG 0
#if DEBUG
//code only sent to the compiler
//if DEBUG is not 0
#endif
你可以使用的预定义符号常量
预处理器还定义了一些你可以使用的符号常量,由名称前后的2个下划线标识,包括。
__LINE__翻译为源代码文件中的当前行__FILE__翻译为文件的名称__DATE__翻译为编译日期,格式为Mmm gg aaaa__TIME__翻译为编译时间,格式为hh:mm:ss