第章編铎预处理 第12章编译预处理 12.1宏定义 22文件包含 23条件编译 BACK
第 12 章 编 译 预 处 理 第 12章 编译预处理 12.1 宏定义 12.2 文件包含 12.3 条件编译
第章編铎预处理 121宏定义 121.1不带参数的宏定义 定义形式: # define宏名宏体 宏名是一自定义标识符,宏体是一字符串,在程序 中可用宏名代表宏体
第 12 章 编 译 预 处 理 12.1 宏定义 12.1.1 不带参数的宏定义 定义形式: #define 宏名 宏名是一自定义标识符,宏体是一字符串,在程序 中可用宏名代表宏体
第章編铎预处理 例如,用P代表3.1415926,用PR代表 printf,宏 定义如下: (1)# define pi3.1415926 (2)# define PR printf 程序中凡是出现3.1415926的地方,都可以以PI出 现,凡是出现 printf的地方,都可以以PR出现
第 12 章 编 译 预 处 理 例如,用PI代表3.1415926,用PR代表printf, 宏 定义如下: (1) #define PI 3.1415926 (2) #definee PR printf 程序中凡是出现3.1415926的地方,都可以以PI出 现, 凡是出现printf的地方,都可以以PR出现
第章編铎预处理 例12-1利用宏定义求圆的周长和面积。 /*程序12-1,利用宏定义求圆的周长和面积* define p3.1415926 t definer l0 main (float 1, S; 1=2.0*PIR; S=PIR*R: printf("周长=%f,面积=%fn",1,s)
第 12 章 编 译 预 处 理 例 12-1 利用宏定义求圆的周长和面积。 /* 程序12 - 1,利用宏定义求圆的周长和面积 */ #define PI 3.1415926 #define R 1.0 main( ) {float l, s; l=2.0*PI*R; s=PI*R*R; printf(″周长=%f, 面积=%f\n″ , l, s); }
第章編铎预处理 上面程序在编译前将进行宏展开,宏展开以后 变为: main() float l, S 1=2.0*3.1415926*1.0; S=3.1415926*1.0*1.0; printf("周长=%,面积%fn",l,s);
第 12 章 编 译 预 处 理 上面程序在编译前将进行宏展开,宏展开以后 变为: main( ) {float l, s; l=2.0*3.1415926*1.0; s=3.1415926*1.0*1.0; printf(″周长=%f, 面积=%f\n″ , l, s); }
第章編铎预处理 (1)宏名一般习惯用大写字母表示,以便与变量名相区 别。当然可以使用小写字母。 (2)宏定义是用宏名简单替换宏体,也就是作简单的置 换,不作语法检査,出现错误也不会报告,只有在宏展开 后编译时才会报告错误。 (3)程序中双引号中与宏名相同的内容不被替换。 (4)宏展开后源程序将变长。 (5)使用宏名,可以减少程序中重复书写某些宏体的工 作量。 (6)宏定义一般放在程序的开头,宏名的有效范围为定 义位置到文件结束 (7)宏定义可以嵌套,后定义的宏可使用已定义的宏
第 12 章 编 译 预 处 理 (1) 宏名一般习惯用大写字母表示,以便与变量名相区 别。当然可以使用小写字母。 (2) 宏定义是用宏名简单替换宏体, 也就是作简单的置 换,不作语法检查, 出现错误也不会报告,只有在宏展开 后编译时才会报告错误。 (3) 程序中双引号中与宏名相同的内容不被替换。 (4) 宏展开后源程序将变长。 (5) 使用宏名, 可以减少程序中重复书写某些宏体的工 作量。 (6) 宏定义一般放在程序的开头, 宏名的有效范围为定 义位置到文件结束。 (7) 宏定义可以嵌套, 后定义的宏可使用已定义的宏
第章編铎预处理 1212带参数的宏定义 定义形式: # define宏名(参数表)宏体 带参数的宏展开时要从左至右进行参数的简单替换, 使用起来较无参数宏定义复杂。 例如: 1)# define S(n (n)*(n)*(n) ( 2)# define T(n) 1/(n) 第一个式子代表n的立方,第二个式子代表n的倒数
第 12 章 编 译 预 处 理 12.1.2 带参数的宏定义 定义形式: #define 宏名(参数表) 带参数的宏展开时要从左至右进行参数的简单替换, 使用起来较无参数宏定义复杂。 例如: (1) #define S(n) (n)*(n)*(n) (2) #define T(n) 1/(n) 第一个式子代表n的立方, 第二个式子代表n的倒数
第章編铎预处理 说明 (1)列出的参数必须在宏体中用到 (2)带参数的宏展开只是将实参简单替换形参。当实参 中含有运算,宏展开可能会出问题。 如有宏定义: # define s(n) n*n'n 若将形参n用实参a+b替换,S(a+b)会变成 a+b*a+b*a+b,显然与原意不相符。 如将宏定义改成: define s(n)(n)*(n*(n) S(a+b)为(a+b)*(a+b)*(a+b),与原意相符 因此,在带参的宏定义中,参数应加括号来描述
第 12 章 编 译 预 处 理 说明: (1) 列出的参数必须在宏体中用到。 (2) 带参数的宏展开只是将实参简单替换形参。当实参 中含有运算,宏展开可能会出问题。 如有宏定义: #define S(n) n*n*n 若将形参 n 用实参 a+b 替 换 , S ( a+b ) 会变成 a+b*a+b*a+b, 显然与原意不相符。 如将宏定义改成: #define S(n) (n)*(n)*(n) S(a+b)为(a+b)*(a+b)*(a+b),与原意相符。 因此, 在带参的宏定义中, 参数应加括号来描述
第章編铎预处理 (3)宏定义时,在宏名与带参数的括号之间不应 加空格,否则将空格以后的部分都作为宏体。例如: t define s(n(n)(n)*(n) S被认为是不带参数的宏名,它代表 (n)(n)*(n)*(n)这样的宏体。 (4)如在宏体中的参数前加上“#”,则在宏展 开后该实参前后会加上双引号,变成字符串
第 12 章 编 译 预 处 理 (3) 宏定义时,在宏名与带参数的括号之间不应 加空格,否则将空格以后的部分都作为宏体。例如: #define S (n)(n)*(n)*(n) S被认为是不带参数的宏名,它代表 (n)(n)*(n)*(n)这样的宏体。 (4) 如在宏体中的参数前加上“#” ,则在宏展 开后该实参前后会加上双引号,变成字符串
第章編铎预处理 例12-2利用带参数的宏定义求圆的周长和面积 /*程序12[CD*2]2,利用带参数的宏定义求圆的周长和面积* tt definer 1.0 tt define pi 3.14159 t define C(r) 2*PI*(r) define s(r) Pl*(r)*(r) main printf("周长=%f,面积=%n",C(R),S(R));}
第 12 章 编 译 预 处 理 例 12 – 2 /*程序12 [CD*2] 2, 利用带参数的宏定义求圆的周长和面积*/ #define R 1.0 #define PI 3.14159 #define C(r) 2*PI*(r) #define S(r) PI*(r)*(r) main( ) {printf(″周长=%f, 面积=%f\n″, C(R), S(R)); }