1.明示常量 #define
预处理指令#define从#开始运行,到后面的第一个换行符为止,在预处理开始前,编译器会把多行物理行处理为一行逻辑行,每行逻辑行都由三部分组成:
- 第一部分是#define指令本身
- 第二部分是选定的缩写,也称为宏(代表值的话就是类对象宏)
- 第三部分是替换列表或替换体
例如:#define PX printf(“x is %d.\n”,x)
2.类函数宏
在#define中使用参数可以创建外形和作用与函数类似的类函数宏,类函数宏定义的圆括号中可以有一个或多个参数,随后这些参数出现在替换体中。
例如:#define MEAN(X,Y) ((X)+(Y)/2)
其中X和Y是宏参数,
3.用宏参数创建字符串 #运算符
例如这个类函数宏:#define PSQR(X) printf(“The square of X is %d.\n)”,((X)*(X)));
如果我们这样用PSQR(8)
就会输出:The square of X is 64
双引号中的X被视为普通文本,而不是一个可被替换的符号,如果想要把X替换为对应的数字,则需要使用#作为预处理运算符#define PSQR(x) printf(“The square of ” #x ” is %d.\n”,((x)*(x)))
4.预处理器粘合剂:##运算符
与#运算符类似,##运算符课用于类函数宏的替换部分,也可以用于对象宏的替换部分,用于把两个记号组合成一个记号
例如:#define XNAME(n) x ## n
这样宏XNAME(4)将展开为x4
5.变参宏:…和_ _VA_ARGS_ _
C99/C11支持变参数的宏,具体语法是把宏参数列表中的参数用三个省略号代替,预定义宏_ _VA_ARGS_ _用在替换部分中,例如:
#define PR(...) printf(_ \_VA\_ARGS_ _)
然后以以下两种方式调用:
PR("Howdy");
PR("weight=%d,shipping=$%.2f\n",wt,sp);
对于第一次调用:_ \_VA\_ARGS_ _展开为一个参数 :"Howdy"
对于第二次调用:_ \_VA\_ARGS_ _展开为三个参数:"weight=%d,shipping=$%.2f\n"、wt、sp
因此展开后的代码是:
printf("Howdy");
printf("weight=%d,shipping=$%.2f\n",wt,sp);
5.#undef指令
该指令用于取消之前的#define指令,假如说有如下定义:#define LIMIT 400,然后下面的指令#undef LIMIT将移除上面的定义,即使原来没有定义LIMIT,取消LIMIT的的定义仍然有效。
6.条件编译
6.1#ifdef、#else和#endif指令
首先,如果预处理器已经了#ifdef后面的标识符,则执行#else或#endif指令之前的所有指令并编译所有C代码(先出现哪个指令就执行到哪里) ,如果预处理器未定义的话,且有#else指令,则执行#else和#endif指令间的所有代码,例如:
#ifdef MAVIS
#include "horse.h" //如果已经用#define命令定义了MAVIS,则执行下面的命令
#define STABLES 5
#else
#include "cow.h" //如果没有用#define定义MAVIS,则执行下面的命令
#define STABLES 15
#endif
6.2#ifndef
该指令与#ifdef指令的用法类似,也可以和#else和#endif一起使用,该指令判断后面的标识符是否是未定义的,常用于定义之前未定义的常量,如:
#ifndef SIZE
#define SIZE 100
#endif
6.3#elif
该指令就像else if 例如:
#if SYS==1
#include "ibmpc.h"
#elif SYS==2
#include "vax.h"
#endif
6.4预定义宏
宏 | 含义 |
---|---|
__DATE__ | 预处理的日期(“Mm dd yyyy”形式的字符串字面量) |
__FILE__ | 表示当前源代码文件名的字符串字面量 |
__LINE__ | 表示当前源代码文件中行号的整型常量 |
__STDC__ | 设置为1时,表示实现遵循C标准 |
__STDC__HOSTED__ | 本机环境设置为1,否则设置为0 |
__STDC_VERSION__ | 支持C99标准,设置为19901L,支持C11标准,设置为201112L |
__TIME__ |
6.5#line 和#error
首先,#line指令重置__LINE__和__FILE__宏报告的行号和文件名,例如:
#line 1000 //把当前行号重置为1000
#line 10 "collic" //把当前行号重置为10,把文件名重置为cool.c
第二,#error指令让预处理器发出一条错误消息,该消息包含指令中的文本例如:
#if __STDC_VERSION__ !=201112L
#error Not C11
#endif
6.6#pragma
该指令把编译器指令放入源代码中