预处理明亮是标准C统一规定的,但它不是C语言本身的一部分,不能直接对它们进行编译。必须在对程序进行通常的编译之前,先对程序的这些特殊命令进行预处理。经过预处理的程序不再包括预处理命令了,最后再由编译程序对预处理后的源程序进行通常的便已处理,得到可以共执行的目标代码。
预处理包括三大类:
1.宏定义
1.不带参数的宏定义
#define 标识符 字符串
在预编译时将宏名替换成字符串的过程称为宏展开。
1.在这个过程中,只是做简单的置换,不作正确性检查;
2.宏定义不是C语句,不必再行末加分号;
3.#define命令出现在程序中函数的外面,宏名的有效范围为定义命令之后到本源文件结束。当然,可以使用#undef命令终止宏定义的作用域。
#define G 10 void main() { ... } #undef G //G的有效范围从定义处到此为止 void f() { ... }
4.在进行宏定义时,可以引用已经定义的宏名,可以层层置换。
5.宏定义是专门用于预处理命令的一个专用名词,它与定义变量的含义不同,只做字符替换,不分配内存空间。
2.带参数的宏定义
#define 宏名(参数表)字符串
例子:
#define PI 3.14159
#define s(r) PI*r*r
如果S(2) ,则宏展开为3.14159*2*2;
如果S(a+b),则宏展开后为3.124159*a+b*a+b -----------------说明宏展开只是简单的字符替换而已
想得到正确的结果,则需这样定义:#define S(r) PI*(r)*(r)
注意:在宏名誉带参数的括号之间不应加空格;否则将空格以后的字符串都作为替代字符串的一部分。
如:#define S (r) PI*r*r 则认为S是符号常量(不带参数的宏名),代表字符串(r)PI*r*r
area= S(a) --> area=(r) PI*r*r(a)
函数调用与宏定义的区别:
1.函数调用,先求出实参表达式的值,然后带入形参;宏只是简单的字符替换
2.函数调用是程序运行时处理的,为形参分配临时的内存单元;而宏展开则是在编译前进行的,在展开时并不分配内存单元,不进行值的传递处理,没有返回值概念
3.函数的实参与形参要定义类型,二者类型要一致,不一致,应该进行类型转换。宏不存在类型问题,宏名无类型,它的参数也无类型,只是一个符号代表,展开时代入指定的字符串即可。
4.调用函数只可以得到一个返回值,而宏可以设法得到几个结果。
5.使用宏次数多时,宏展开后源程序变长,因为每展开一次都使程序增长,而函数调用不会使源程序变长。
6.宏替换不占运行时间,只占编译时间。而函数调用则占运行时间(分配单元,保留现场,值传递,返回)
2.文件包含
#include <文件名>:到存放C库函数头文件的目录中寻找要包含的文件
#include "文件名" :先在当前目录中寻找要包含的文件,若找不到,再按标准方式查找(尖括号方式查找)
3.条件编译
语法方式一:
#ifdef 标识符 程序段1 #else 程序段2 #endif
其中#else可以没有
#ifdef 标识符 程序段1 #endif
语法方式二:
#ifndef 标识符 程序段1 #else 程序段2 #endif
语法方式三:
#if 标识符 程序段1 #else 程序段2 #endif
不用条件编译命令而直接用if语句也能达到要求,那么好处是什么呢?
用if语句处理的话,目标程序长(所有语句都需要编译),运行时间长;而采用条件编译,可以减少被编译的语句,从而减少目标程序的长度,减少运行时间。当条件编译比较多时,目标程序长度可以大大减少。