1.ANSI C定义的标准预处理指令
#if#ifdef
#else
#elif
#endif
#define
#undef
#line
#error
#pragram
#include
预处理器处理的对象是预处理指令(preprocessor directives),输出是“翻译单元"(是存放在内存中的临时文件).
编译器接受预处理器的输出,并把源代码转换成机器语言指令的目标文件
第一步:编译预处理
编译预处理之后还是源代码,不是机器指令,仅仅是翻译的过程
2.书写规定与习惯
1)每条指令必须单独占用一行2)每行末尾不加;(因为不是一句)。
3)一般使用全部大小写来表示标识符。
如:#define LANGUAGE chinese -->用LANGUAGE代替chinese,预处理阶段difine都是当做字符串处理。LANGUAGE这里被叫做宏,chinese成为宏体
4)一个预处理指令可以写在程序中的任何位置。通过合理地使用这些指令,可以提高程序的可读性和可移植性。
3.关于#define的一些说明
1)宏中的参数只原样替换,并不求值,而函数的参数则不然2) 宏中的参数不会被分配内存空间。因为都是字符串
3)宏只会占用编译时间,而不占用运行时间,但函数则相反
4) 宏被替换后,可能使代码加长,而函数则不会。使用函数的一个主要目的就是使代码可以重用,可以起到简化代码的作用。
5)宏比函数具有更好的数据类型的适应性(因为它没有参数类型的要求)
6) 宏不能被递归调用
使用类函数宏代替函数的一个主要优点是能提高代码的速度(消除了调用的开销)。但是,若类函数的尺度非常大,则会因为复制代码而增加了程序的开销。
例子
#include <stdio.h>
#define Max(a,b) ((a)>(b)?(a):(b))
int max(int a,int b)
{
return (a>b)?a:b;
}
void main()
{
Max(2+4,3+5);//==>((2+4)>(3+5)?(2+4):(3+5)),因为是宏替换,所以带括号
max(2+4,3+5);//执行效率比宏定义执行效率慢,因为宏定义不涉及到类型检查
//因为宏定义不进行类型检查Max(2.0+4.0,'a'+b);可以编译通过,max(2.0+4.0,'a'+b);就不行
}
4.关于#include的一些说明
1)文件包含是一种模块化程序的手段,有助于代码的重用2)习惯:程序员可以将经常使用的常量(宏定义),多个源文件共同使用的全局变量,函数声明等写成一个或分类写成多个文件(头文件),在需要时,可以用#include将它们(头文件)包含进来
3)包含文件中允许嵌套包含(可以包含其他#include指令)。允许的最大潜逃深度随编译器的不同而不同。C89规定编译器最少能处理8层嵌套包含,C99提升到15层
5.关于条件编译的一说说明
1)条件编译是为了使得商业软件具有更广泛的适应性(或可移植性)而提供的功能。2)C89规定,#if -- #endif,#ifdef和#ifndef的嵌套深度最少为8层,C99提升到63层
3) 例子1:
#ifdef IBM-PC
#define INTSIZE 2
#else
#define INTSIZE 4
#endif
例子2:符号NULL在6个不同的文件中都有定义:locate.h,stddef.h,stdio.h,stdlib.h,string.h,time.h.一个源文件可能包含其中几个头文件,这样会使得编译器报错,这时需要在每个头头文件中使用条件编译:
#ifndef NULL
#define NULL((void *)0)
#endif