C程序涉及很多步骤,第一个步骤预处理阶段。任务是删除注释、插入被#include
的文件、定义和替换由#define
指令定义的符号以及确定代码是否根据一些条件编译指令进行编译。
1.预定义符号
__FILE__
和__LINE__
用于调试,__DATE__
和__TIME__
版本信息等。
符号 | 样式值 | 含义 |
---|---|---|
FILE | “name.c” | 进行编译的源文件名 |
LINE | 25 | 文件当前行的行号 |
DATE | “jan 31 1997” | 文件被编译的日期 |
TIME | “18:04:30” | 文件被编译的时间 |
STDC | 1 | 如果遵循ANSIC为1,否则未定义 |
2.#define
define后面很长,除最后一行外,每行末尾都要加一个反斜杠
#define DEBUG_PRINT printf("file %s line %d:" \
"x=%d,y=%d,z=%d", \
__FILE,__LINE__,
x,y,z)
利用了相邻字符串常量被自动连接为一个字符串这个特性。很方便调用调试
x*=2;
y*=x;
z*=x*y;
DEBUG_PRINT;
注意define后面不能加;
否则下面的语句会有问题.因为两分号相当于多了一个空的语句。
if()
DEBUG_PRINT;
else
...
2.1 #define替换
程序扩展#define
定义符号的宏时,需要涉及几个步骤:
- 1.调用宏时,首先对参数进行检查,看是否包含了由
#define
定义的符号,如果是它们首先被替换。 - 2.替换文本随后被插入到程序中原来文本位置。对于宏,参数被他们的值所替代。
- 3.最后再对结果进行扫描,看看是否包含
#define
定义的符号。
技巧1.可将字符串分段的技巧:
#define PRINT(FORMAT,VALUE) \
printf("The value is "FORMAT"\n",VALUE)
...
PRINT("%d",x+3);
技巧2.使用预处理器把一个宏参数转换成一个字符串,#argument
这种被翻译成argument
.
#define PRINT(FROMAT, VALUE) \
printf("The value of #VALUE \
" is " FROMAT "\n",VALUE)
PRINT("%d",x+3);
//输出:
//The value of x+3 is 25
技巧3. ##
结构执行一种不同的任务。把位于它两边的符号连接成一个符号。允许宏定义从分离的文本片段创建标识符。
#define ADD_TO_SUM(sum_number,value) \
sum ## sum_number +=value
...
ADD_TO_SUM(5,25);
//翻译结果:sum5+=25;
3.#undef
这条预处理指令用于移除一个宏定义.
#undef name
条件编译
条件编译,可以选择代码一部分是否被编译,还是完全忽略。
#if constant-expression
statements
#endif
- constant-expression(常量表达式)由处理器进行求值。如果是非零(真),statements将会被编译,否则编译器安静地删除它们。
常量表达式,就是它或者是字面值常量,或者是一个由#define定义符号
。
#if DEBUG
printf("x=%d\n",x,y);
#endif
如果想编译它,只要使用#define DEBUG 1
.如果忽略它,只要把这个符号定义为0,即#define DEBUG 0
.还支持多分枝结构
#if constant-expression
statements;
#elif constant-expression
other statements;
#else
other statements
#endif
多个不同的版本的维护,条件编译可以解决这个问题:
if(feature_selected==FEATURE1)
#if FREATURE1_ENABLED_FULLY
feature1_function(arguments);
#elif FREATURE1_ENABLED_PARTIALLY
featrure1_partial_function(arguments);
#endif
是否被定义
测试一个符号是否已经被定义也是有可能的。测试可以通过下列方式任何一种:
//1.
#if defined(symbol)
#ifdef symbol
//2.
#if !define(symbol)
#ifndef symbol
两种定义都可以的,但是#if
更强大,常量表达式可能包含额外的条件:
#if X>0 || defined(ABC) && defined(BCD)