预处理程序可能的动作:1. 包含其他文件 (#include <filename>/"filename")
2. 定义符号常量和宏 (#define 符号常量/宏)
3. 程序代码的条件编译 (#ifdef和#ifndef)
4. 预处理指令的条件执行
以下将以上面为提纲说明。
1. #include的两种用法:
A. #include "filenameA" :表示在正在编译的程序所在的目录中查找filenameA 文件,通常用于自定义的头文件。
B. #include <filenameB> :表示查找标准头文件(如 stdio.h和stdlib.h),在预定义的目录中查找filenameB。
2. #define用法:
#define用于建立符号常量(用符号定义的常量)和宏(用符号定义的操作)
2.1 #define:符号常量
例: #define PI 3.1415
给常量取有意义的名字可以提高程序的可读性
2.2 #define: 宏
宏是#define中定义的一种操作,和符号常量一样,程序中的宏标识符将在程序编译之前呗替换文本替换。
带参数的宏:先用替换文本取代参数,然后将宏展开(即,先用数值替换参数,然后对展开宏的表达式进行计算)
例:求圆面积 #define CIRCLE_AREA (x) (PI*(x)*(x))
若程序中语句为 area=CIRCLE_AREA(4);被展开为:area=(3.1415*(4)*(4));
注意:1.在宏定义中,x加括号是必要的,宏只进行机械的替换,如:
#define CIRCLE_AREA (x) (PI*x*x)
语句:area=CIRCLE_AREA (c+3);被展开之后为:area=
(3.1415*c+3*c+3)这是常见的错误。
2. 宏或符号常量的替换文本超过一行时,需要在该行的末尾加上反斜杠(/),
表示替换文本继续到下一行。
2.3. #undef
可以用#undef结束符号常量和宏的作用。符号常量和宏名的作用域从其定义开始到用
#undef取消其定义或到文件结束为止。
注意:有副作用的表达式(即修改变量的表达式)不应该传递给宏,因为宏的参数可能
被多次计算。(例如:area=CIRCLE_AREA (++c)?,有点糊涂)
3. 条件编译
与if的结构和功能都类似 #if !defined(NULL) //确定是否定义了NULL
#define NULL 0 //是,则条件defined(NULL)=1
#endif
一些缩写: #if defined() ----------------- #ifdef
#if !defined() ----------------- #ifndef
可以用#elif(等价于if结构的else if)和#else(等价于if结构中的else)测试不同条件的预处
理结构。
3.1 新的注释方法
很多情况下,/*和*/不能完成大段的注释,此时可以采用如下的预处理结构
#if 0
被注释的大段代码
#end if
需要让编译器编译这段代码时,只需要将0改为1即可。
3.2 条件编译通常用来帮助调试程序
可以用来控制printf语句的输出,例如
#ifdef DEBUG
printf ("variable x=%d /n",x);
#endif
如果在#ifdef DEBUG之前定义过符号常量DEBUG(即 #define DEBUG),就编译printf
语句,完成调试之后,去掉#define DEBUG的定义即可。
4. 宏 assert
在头文件assert.h中定义的宏assert来测试表达式的之。如果表达式的值为0,那么assert
就打印出错误保温,并调用通用实用库stdlib.h中的函数abort来终止程序的执行。
这是个很有用的调试工具,测试一个变量是否有某个正确的值。
例:assert(x<=10);
如果x>10,则打印出行号和文件名的错误报文并终止程序执行。如果在程序中给出
#define NDEBUG
其后所有的assert将被忽略,而无需手动删除。
以上是学习预定义程序的一个小结,参考《C程序设计教程》。