l 编译预处理命令不属于C语言的范畴,为了与一般的C语言相区别,所有预处理命令都以#开头,一般独占一行,且不加分号结尾。如果一行写不下,可以在行尾放一个反斜杠“/”并以回车键结束,在下一行继续写。编译预处理命令一般放在源程序的首部,但也可以放在程序的其他位置。C语言提供的预处理命令一共有三类:宏定义,文件包含和条件编译。
l 不带参宏定义:
#define 宏名 宏体
定一个宏名来表示一个宏体。宏名一般采用大写。宏体可以是常量,关键字,语句和表达式,也可以是空白。编译预处理阶段,进行宏替换(也叫宏展开,就是用宏体替换掉宏名),然后再替换后的源程序进行编译。
符号常量:定义宏名来代表经常用到的一些常量。
1. 双引号(“”)中的宏不会被替换。
2. 宏替换是将宏体替换成宏名,就是完全的字符复制。如:
#define PI 3.1415926; 则:
a=2*PI*r;óa=2*3.1415926;*r;//所以不要在预处理命令后面加分号
3. 允许层层替换
#define A=20
#define B A-5
则:c=35*B;óc=35*20-5;//注意不是c=35*(20-5);说明了宏替换是完全的字符复制。
l 带参数宏定义
#define 宏名(参数) 宏体
例如:
#define MAXVAL(x, y) (x)>(y)? (x) : (y)
注意:
1. 对于宏展开后容易引起误会的表达式,在宏定义是需要将表达式用圆括号括住。如:
#define SQR(X) X*X
则:s=15/SQR(10);ós=15/10*10;
可以这样:
#define SQR(X) (X*X)
则:s=15/SQR(10);ós=15/(10*10);
2. 定义宏的时候,注意宏名与参数列表的圆括号之间不要有空格,否则系统会将空格之后的内容当作宏体进行替换。
l 宏定义的解除
#undef 宏名
1. 带参数的宏定义时,只需要给出宏名而不必给出参数。
2. 解除宏定义的一个作用就是在解除宏定义之后可以对这个宏名重新定义。在实际应用中,有多个源文件组成的程序,在不同的源文件中可能会出现同名的宏名被定义为不同的宏体,当这些文件合并在一起的时候,就会出现重复定义的错误,为避免这样的错误,一般在源文件的结尾将本文件定义的宏名用#undef解除。
l 文件包含
#include <文件名> 或者#include “文件名”
头文件的内容一般包含宏定义,结构类型定义和全局变量定义等。
有关文件包含命令的说明:
1. 一个#include命令只能指定一个要包含的头文件。一个文件可以有多个包含命令。
2. #include<文件名> :<>包住头文件时,预处理程序只在存放C库函数头文件的标准目录(TC/include)中搜索要包含的头文件,称为标准形式。
3. #include”文件名”:””包住头文件时,且没有指定文件目录时,预处理程序首先在源文件所在的目录中寻找头文件,若找不到,再到标准目录中搜索。也可以在””中指定文件所在的目录,这样系统按指定目录搜索。
l 条件编译:对部分程序,满足一定条件时才编译执行,从而使同一个源程序在不同条件下能够编译产生不同的代码。条件编译有三种编译形式;
1. #ifdef 标识符
程序段1
[#else
程序段2]
#endif
如果定义了标识符为宏名,则编译执行程序段1;否则执行程序段2。其中[#else 程序段2]部分可以省略。
2. #ifdef 标识符
程序段1
[#else
程序段2]
#endif
如果标识符没有被定义,则编译执行程序段1;否则执行程序段2。其中[#else 程序段2]部分可以省略。
3. #if 表达式1
程序段1
[#elif 表达式2
程序段2]
[#else
程序段n]
#endif
格式中的表达式是常量表达式,不能含变量。因此它常与#define联用,即用符号常量构成常量表达式。例如:
#define N 10
#if N<10
…
#elif N>10
…
#else
…
#endlif