一、预处理器
1) C预处理器在程序执行之前查看程序(故称之为预处理器)
2) 根据程序中的预处理器指令,预处理器把符号缩写替换成其表示的内容
3) 预处理器可以包含程序所需的其他文件,可以选择让编译器查看哪些代码
1.预处理之前
在预处理之前,编译器必须对该程序进行一些翻译处理
1.首先,编译器把源代码中出现的字符映射到源字符集
2.编译器定位每个反斜杠后面跟着换行符的实例,并删除它们
// “换行符”的意思是通过按下Enter键在源代码文件中换行所生成的字符,而不是指符号表征\n
// 预处理表达式的长度必须是一个逻辑行
3.编译器把文本划分为预处理记号序列、空白序列和注释序列(记号是由空格、制表符或换行符分隔的项)
// 编译器将用一个空格字符替换每一条注释
// 实现可以用一个空格替换所有的空白字符序列
2.明示常量: #define
1) ANSI和后来的标准都允许#前面有空格或制表符,而且还允许在#和指令的其余部分之间有空格
2) 指令可以出现在源文件的任何地方,其定义从指令出现的地方到该文件末尾有效
3) 预处理器指令从#开始运行,到后面的第一个换行符为止
/* 简单的预处理示例 */
#include<stdio.h>
#define TWO 2
#define OW "Consistency is the last refuge of the unimagina\
tive.-Oscar Wilde" //反斜杠把该定义延续到下一行
#define FOUR TWO*TWO
#define PX printf("X is %d.\n",x)
#define FMT "X is %d.\n"
int main()
{
int x = TWO;
PX;
x = FOUR; //x = TWO*TWO
printf(FMT, x);
printf("%s\n", OW);
printf("TWO: OW\n");
return 0;
}
4) 每行#define(逻辑行)都由三部分组成
1.第一部分是#define指令本身
2.第二部分是选定的缩写,也称为宏(宏的名称中不允许有空格,而且必须遵守C变量的命名规则)
// 有些宏代表值,这些宏被称为类对象宏
// C语言还有类函数宏
// 宏的名称只能使用字符、数字和下划线_字符,而且首字符不能是数字
3.第三部分称为替换列表或替换体
5) 一旦预处理器在程序中找到宏的实例后,就会用替换体代替该宏(有例外)
6) 从宏变成最终替换文本的过程称为宏展开
7) 预处理器不做计算,不对表达式求值,只进行替换
3.在#define中使用参数
1) 在#define中使用参数可以创建外形和作用与函数类似的类函数宏
2) 类函数宏定义的圆括号可以有一个或多个参数,随后这些参数出现在替换体中
3) 函数调用在程序运行时把参数的值传递给函数;宏调用在编译之前把参数记号传递给程序
例: #define SQUARE(X) X*X
z = SQUARE(2);
/* 带参数的宏 */
#include<stdio.h>
#define SQUARE(X) X*X //SQUARE是宏标识符,SQUARE(X)中的X是宏参数,X*X是替换列表
#define PR(X) printf("The result is %d.\n",X)
int main()
{
int x = 5;
int z;
printf("x = %d\n", x); //x = 5
z = SQUARE(x);
printf("求值 SQUARE(x): ");
PR(z); //25
z = SQUARE(2);
printf("求值 SQUARE(2): ");
PR(z); //4
printf("求值 SQUARE(x+2): ");
PR(SQUARE(x + 2)); //17
printf("求值 100/SQUARE(2): ");
PR(100 / SQUARE(2)); //100
printf("x = %d\n", x); //5
printf("求值 SQUARE(++x): ");
PR(SQUARE(++x)); //49
printf("x = %d\n", x); //7
return 0;
}
4.用宏参数创建字符串: #运算符
1) C允许在字符串中包含宏参数;在类函数宏的替换体中,#号作为一个预处理运算符,可以把记号转换成字符串
2) 如果x是一个宏形参,那么#x就是转换为字符串"x"的形参名,这个过程称为字符串化
#include<stdio.h>
#define PSQR(x) printf("The square of "#x" is %d.\n",((x)*(x)))
int main()
{
int y = 5;
PSQR(y); //The square of y is 25.
PSQR(2+4); //The square of 2+4 is 36.
return 0;
}
5.预处理粘合剂:##运算符
##运算符可用于类函数宏的替换部分,可用于对象宏的替换部分
#include<stdio.h>
#define XNAME(n) x##n
#define PRINT_XN(n) printf("x"#n"=%d\n",x##n);
int main()
{
int XNAME(1) = 14;