如果您无法下载资料,请参考说明:
1、部分资料下载需要金币,请确保您的账户上有足够的金币
2、已购买过的文档,再次下载不重复扣费
3、资料包下载后请先用软件解压,在使用对应软件打开
12.1了解编译预处理12.2宏定义定义中的“标识符”称为“宏名”。这一命令的作用仅仅是表明用指定的宏名来代替一个指定的字符串。例如:#definePI3.1415926它的作用是指定用宏名PI来代替“3.1415926”这个字符串。在预编译时,程序中所有出现“宏名”的地方,都将由这个字符串的内容进行替换,此过程称为“宏展开”。说明(1)不带参数的宏定义常常被用于定义符号常量。这样既可以提高程序的通用性,也便于修改。例12.1用宏名限定数组的大小。#defineN10/*定义宏名N*/voidArrIn(inta[]){inti;for(i=0;i<N;i++)/*为N个元素赋值*/scanf("%d",&a[i]);}main(){intx[N];/*定义有N个元素的数组*/ArrIn(x);…}以上是我们在编程中常用的方法:首先利用宏定义指定用N代表字符串10;所以主函数中定义的数组大小是10;函数ArrIn中读入的元素个数也是10。当需要改变数组大小时,只需改动#define命令行,而不用改动程序的其他部分。(2)宏展开时系统不作语法检查,若定义不当,要待编译展开源程序时,才会引发错误。例如:#definePI3.141592bmain(){floats,r=2.5;s=PI*r*r;printf("s=%f\n",s);}程序中在定义代表值的宏名PI时,将字符串3.1415926中的数字6误写作了字母b。这一宏定义命令本身并不构成错误。因为宏名PI代表的是字符串“3.141592b”,而不是数值。但在程序中引用了宏名PI来计算圆面积,赋值语句:s=PI*r*r;经宏展开后变为:s=3.141592b*r*r;从而导致编译出错。虽然出错位置在此赋值语句,但引发这一错误的根源还是上述宏定义命令。(3)宏展开时,不对双引号括起来的字符串中的内容进行替换。如有定义:#definePI3.14159语句:printf("PI=%f\n",PI);中有2个PI,第一个PI是在双引号内的,它不被替换;第二个PI在双引号外,它将被展开成3.14159。(4)在#define命令行中可以没有“字符串”,即表示成:#define标识符如:#defineDEBUG这里仅仅是为了表明标识符DEBUG已经“被定义”。这种定义形式在条件编译中将会用到。(5)为了与变量名相区别,一般习惯用大写字母作宏名。但这不是规定,只是约定俗成。12.2.2带参数的宏定义1.定义形式#define宏名(形参表)字符串例如:#defineCYC(r)2*3.14159*r说明(1)这里定义了一个计算圆周长的宏CYC(r),宏名CYC与其后的左括号之间不得留有空格,否则CYC将被视为不带参数的宏。(2)作为替换文本的字符串中应含有括号中的参数,如2*3.14159*r中的r。否则,就没有必要定义带参数的宏。(3)字符串中可以包含已经定义过的宏名。例如:#defineCR"\n"#defineD"%d"#definePRIDCR则语句:printf(PRI,20);执行后的输出结果为:20。2.宏展开的过程程序中若调用了带参数的宏,预编译时不仅仅是进行简单的字符串替换,还涉及到参数的替换。宏展开的过程是:按命令行中指定的字符串从左到右进行置换,遇到形参则以实参代替,对于非参数字符则原样保留。若有语句:x=CYC(2.5);宏展开时将用实参2.5替换字符串“2*3.14159*r”中的形参r,其他字符不变。置换后的语句为:x=2*3.14159*2.5;说明(1)由于宏定义是在预编译时展开的,它不具有任何计算功能。宏展开时,若实参是一个表达式,也是原样置换,而不进行求值。如有语句:y=CYC(3+5);这里用实参3+5替换“2*3.14159*r”中的形参r后得到:y=2*3.14159*3+5;而不是:y=2*3.14159*8;/*3和5不能先做加法运算*/(2)显然,为确保宏调用的正确性,在定义宏时,应将字符串中的形参用括号括起来。例如:#defineCYC(r)2*3.14159*(r)这时将语句y=CYC(3+5);展开后为:y=2*3.14159*(3+5);有时还需要在整个字符串外面加括号。如对于以下定义的计算两数之和的宏:#defineADD(x,y)x+y若宏调用形式为:k=2*ADD(3,4);展开后为:k=2*3+4;显然与设计意图不符,这时宏定义应改写作:#defineADD(x,y)(x+y)3.带参数的宏与函数的主要区别通过前面的举例,读者可能会觉得:在定义宏时有形参