通常的编译(包括词法分析、语法分析、代码生成、代码优化)之前,先对这些命令进 行预处理,然后将预处理的结果和源程序一起再进行通常的编译处理,以得到目标代码 (oBJ文件)。 C提供的编译预处理命令 宏命令( Macro) 文件包含命令( include) 条件编译命令 这些命令均以#开头,以区别于语句。 宏( Macro) 、不带参数的宏 般形式:# define标识符字符串 如:# define p31415926 作用:用标识符(称为“宏名”)P代替字符串“31415926” 在预编译时,将源程序中出现的宏名P替换为字符串“31415926”,这一替换过程称为“宏 展开”。 # define:宏定义命令 fd终止宏定义命令
编译预处理:在源程序文件中,加入“编译预处理命令”,使编译程序在对源程序进行 通常的编译(包括词法分析、语法分析、代码生成、代码优化)之前,先对这些命令进 行预处理,然后将预处理的结果和源程序一起再进行通常的编译处理,以得到目标代码 (OBJ文件)。 C提供的编译预处理命令 宏命令(Macro) 文件包含命令(include) 条件编译命令 这些命令均以#开头,以区别于语句。 宏(Macro) 一、不带参数的宏 一般形式:#define 标识符字符串 如: #define PI 3.1415926 作用:用标识符(称为“宏名”)PI代替字符串“3.1415926”。 在预编译时,将源程序中出现的宏名PI替换为字符串“3.1415926” ,这一替换过程称为“宏 展开”。 #define:宏定义命令 #undef:终止宏定义命令
#define Pl3. 1415926 main( float ls,r,v: printf(" input radius: B scanf("%f",&r);/*输入圆的半径* 1=20*P*r;/*圆周长* s=P*r*r;/*圆面积* V=40/30*P*r*r*r;/*球体积* printf(" 1=%104f\ns=%104f\nv=%104f\n",L, s, v); 关于宏定义的说明:
[例] #define PI 3.1415926 main() { float l,s,r,v; printf("input radius:"); scanf("%f",&r); /* 输入圆的半径*/ l = 2.0*PI*r; /* 圆周长*/ s = PI*r*r; /* 圆面积 */ v = 4.0/3.0*PI*r*r*r; /* 球体积 */ printf("l=%10.4f\ns=%10.4f\nv=%10.4f\n",l,s,v); } 关于宏定义的说明:
般去名用大写字母表示。(变量名一般用小写字母) 2、使用宏可以提高程序的可读性和可移植性。如上述程序中,多处需要使用π 值,用宏名既便于修改又意义明确 3、宏定义是用宏名代替字符串,宏扩展时仅作简单替换,不检查语法。语法检 查在编译时进行。 4、宏定义不是C语句,后面不能有分号。如果加入分号,则连分号一起替换。 #define pl 3. 1415926 area= p*rr: 在宏扩展后成为: area=31315926;*r*r; 结果,在编译时出现语法错误。 5、通常把# define命令放在一个文件的开头,使其在本文件全部有效。(# define 定义的宏仅在本文件有效,在其它文件中无效,这与全局变量不同)。 6、宏定义终止命令unde结束先前定义的宏名
1、一般宏名用大写字母表示。(变量名一般用小写字母)。 2、使用宏可以提高程序的可读性和可移植性。如上述程序中,多处需要使用π 值,用宏名既便于修改又意义明确。 3、宏定义是用宏名代替字符串,宏扩展时仅作简单替换,不检查语法。语法检 查在编译时进行。 4、宏定义不是C语句,后面不能有分号。如果加入分号,则连分号一起替换。 如: #define PI 3.1415926; area = P*r*r; 在宏扩展后成为: area = 3.1315926;*r*r; 结果,在编译时出现语法错误。 5、通常把#define命令放在一个文件的开头,使其在本文件全部有效。(#define 定义的宏仅在本文件有效,在其它文件中无效,这与全局变量不同)。 6、宏定义终止命令#undef结束先前定义的宏名
define g 9. 8 需 # undef g/*取消G的意义*/ f10 7、宏定义中可以引用已定义的宏名。 例82] #definer.0 #define pl3. 1415926 #deinfe l Pi*r #define s pi rr maino printf("L=%f\ns=%f\n", L, S
#define G 9.8 main() { } #undef G /* 取消G的意义 */ f1() ┆ 7、宏定义中可以引用已定义的宏名。 [例8.2] #define R 3.0 #define PI 3.1415926 #deinfe L 2*PI*R #define S PI*R*R main() { printf("L=%f\nS=%f\n",L,S); }
8对程序中用双引号括起来的字符串,即使与宏名相同,也不替换。例如上例 的 printi语句中,双引号括起来L和S不被替换。 二、带参数的宏 般形式: # define宏名(参数表)字符串 带参数的宏在展开时,不是进行简单的字符串替换,而是进行参数替换。例、 #define s(a,b) 其中*保留 area=S(3,2)得3w2
8、对程序中用双引号括起来的字符串,即使与宏名相同,也不替换。例如上例 的printf语句中,双引号括起来L和S不被替换。 二、带参数的宏 一般形式: #define 宏名(参数表)字符串 带参数的宏在展开时,不是进行简单的字符串替换,而是进行参数替换。例
#define pi 3.1415926 #define S(r) Pl*r*r main( I float a, area a=3.6; area= Sa; printf("r=%f\narea=%f\n", a, area); 说明 带参数的宏展开时,用实参字符串替换形参字符串,注意可能发生的错误。比 较好的办法是宏定义的形参加括号。 宏定义 语句 展开后 #dene()PI*r*xrea=()area三F工*a十b*a十b # define S(r)PI*()*(x)are=S(a+b);axea=P工*〔a十b〕*〔a+b〕
[例] #define PI 3.1415926 #define S(r) PI*r*r main() { float a, area; a = 3.6; area = S(a); printf("r=%f\narea=%f\n",a,area); } 说明: 带参数的宏展开时,用实参字符串替换形参字符串,注意可能发生的错误。比 较好的办法是宏定义的形参加括号
例]返国多个值的宏定义。 #define p 3.1415926 #define CIRCLE(R, L, S, V)L=2*PI*R; S=PI*R *R; v=4/3*PI*R*R*R float rls. v;/*半径、圆周长、圆面积、球体积* scanf("%f,&r) CIRCLE(r, l, s, v); printf(r=%6.2f, 1=%6.2f, s=%6.2f, v=%6.2f\n",r,L, s, v); 输出结果:
[例] 返回多个值的宏定义。 #define PI 3.1415926 #define CIRCLE(R,L,S,V) L=2*PI*R;S=PI*R*R;V=4/3*PI*R*R*R main() { float r,l,s,v; /*半径、圆周长、圆面积、球体积 */ scanf("%f",&r); CIRCLE(r,l,s,v); printf("r=%6.2f,l=%6.2f,s=%6.2f,v=%6.2f\n",r,l,s,v); } 输出结果:
例]输出格式定义为宏 ma ino #define PR printf f int a, b, c, d #define nl"\n char string[]="CHINA" #define d%d a=1;b=2;c=3;d=4; #define d1 d nl PR(D1,a; #define d2DD nl PR(D2, a, b); #define d3Ddd nl PR(D3, a, b, c); #define dddd nl PR(D4, a, b, c, d); #defines %s PR(S,string); 输出结果:
[例] 输出格式定义为宏 #define PR printf #define NL "\n" #define D "%d " #define D1 D NL #define D2 D D NL #define D3 D D D NL #define D4 D D D D NL #define S "%s" main() { int a,b,c,d; char string[] = "CHINA"; a = 1; b = 2; c = 3; d = 4; PR(D1,a); PR(D2,a,b); PR(D3,a,b,c); PR(D4,a,b,c,d); PR(S,string); } 输出结果:
82文件包含(# nclude) 文件包含命令的一般格式是: # include"文件名" 作用:预处理时,把“文件名”指定的文件内容复制到本文件,再对合并后的文件进行 编译。 例 file1. c file2. c file1.c #include " file2 cl B B A
8.2 文件包含(#include) 文件包含命令的一般格式是: #include "文件名" 作用:预处理时,把“文件名”指定的文件内容复制到本文件,再对合并后的文件进行 编译。 例
在什e1文件中,有文件包含命令荆 nclude"fie2c",预处理时,先把fe2c的内 容复制到文件fe1c,再对fle1c进行编译。 从理论上说,# nclude命令可以包含任何类型的文件,只要这些文件的内容被扩 展后符合C语言语法。 般# include命令用于包含扩展名为h的“头文件”,如 stdio.h、 string h、 math . h。在这些文件中,一般定义符号常量、宏,或声明函数原型。 程序员也可以把自己定义的符号常 (2)文件fe1c 量、宏,或函数原型放在头文件中,# nclude" print format. ht“ 用# include命令包含这些头文件。 maino (1)文件 print format. h i int a, b, c, d; #define Pr printf har string[门="CHNA"; #define Nl"\n a=1;b=2;c=3;d=4; #define d%d PR(D1, a); #define d1 d nl PR(D2, a, b) #define d2DD nl PR(D3, a, b, c); #define d3ddD nl PR(D4, a, b, c, d); #define Dddd nl PR(S,string S%s
在file1.c文件中,有文件包含命令#include "file2.c",预处理时,先把file2.c的内 容复制到文件file1.c,再对file1.c进行编译。 从理论上说,#include命令可以包含任何类型的文件,只要这些文件的内容被扩 展后符合C语言语法。 一般#include命令用于包含扩展名为.h的“头文件”,如stdio.h、string.h、 math.h。在这些文件中,一般定义符号常量、宏,或声明函数原型。 程序员也可以把自己定义的符号常 量、宏,或函数原型放在头文件中, 用#include命令包含这些头文件。 (1)文件print_format.h #define PR printf #define NL "\n" #define D "%d " #define D1 D NL #define D2 D D NL #define D3 D D D NL #define D4 D D D D NL #define S "%s" (2)文件file1.c #include "print_format.h“ main() { int a,b,c,d; char string[] = "CHINA"; a = 1; b = 2; c = 3; d = 4; PR(D1,a); PR(D2,a,b); PR(D3,a,b,c); PR(D4,a,b,c,d); PR(S,string); }