使用带参数宏定义时,除了前面提到的使用宏定义预处理的注意事项外,还要注意下面几点:①带参宏定义中,宏名和形参表之间不能有空格出现。②带参宏定义中,形式参数不分配内存单元,因此不必作类型定义。而带参数的宏对实参表达式不作计算直接照原样代换,只是进行简单的替换。③带参数宏的形式参数与函数中的形式参数不同,它没有确定的数据类型。带参数宏调用替换问题的理解示例。......
2023-11-20
宏也可以带参数,其定义的一般形式为:
#define标识符(参数列表) 字符串
其中标识符是宏名,字符串中包含括号内指定的参数,称为宏扩展。例如:
#define area(r) (3.1415926*(r)*(r))
这里r作为宏area的参数,定义之后可在程序中使用它。例如:
我们注意到这里宏的名字用的是小写字母。这时由于带参数的宏从形式上看很像函数,为了统一,多数人在定义带参数的宏时喜欢使用小写字母。
宏也可以带多个参数。例如,求两个数中较大者,我们可以定义宏
#define max(x,y) ((x)>(y)?(x):(y))
如果在程序中出现语句
m=max(a,b);
则预处理时替换为
m=((a)>(b)?(a):(b));
使用带参数的宏编写程序时,要特别注意两点:
(1)在宏定义中宏名和括起参数的左圆括号之间不能有空格。
如果宏定义为
#define area(r) (3.1415926*(r)*(r))
则语句
printf(“%f\n”,area(2.0));
被替换为(www.chuimin.cn)
printf(“%f\n”,(r) (3.1415926*(r)*(r))(2.0));
这显然是不对的。因为预处理程序把area认做是一个不带参数的宏,只是简单地把其后所跟字符串原样搬到area处。
(2)整个宏扩展及各参数要用括号括起,就像前面给出的例子那样。如果不用括号括起会出现什么情况呢?例如,我们来定义一个求平方的宏。
#define square(x)x*x
如果有语句
a=square(n+1);
则预处理时被替换为
a=n+1*n+1;
结果是把2*n+1赋给了a,显然这不是我们所期望的
a=(n+1)*(n+1);
宏扩展中最外层的括号也是必要的。如果不要最外层的括号,宏定义写成
#define square(x) (x)*(x)
如果遇到下面的语句调用宏
printf(“%d\n”,27/square(3));
我们可以先猜猜看输出结果是什么。是3吗?让我们替换一下,变成
printf(“%d\n”,27/(3)*(3));
由于*和/同级,并按从左到右顺序计算,所以表达式27/(3)*(3)的值为27,这不是我们所期望的值,这就是为什么我们要用括号括起整个宏扩展了。
有关C语言程序设计 第2版的文章
使用带参数宏定义时,除了前面提到的使用宏定义预处理的注意事项外,还要注意下面几点:①带参宏定义中,宏名和形参表之间不能有空格出现。②带参宏定义中,形式参数不分配内存单元,因此不必作类型定义。而带参数的宏对实参表达式不作计算直接照原样代换,只是进行简单的替换。③带参数宏的形式参数与函数中的形式参数不同,它没有确定的数据类型。带参数宏调用替换问题的理解示例。......
2023-11-20
不带参数的宏定义一般形式是:#define宏名字符串例如:#definePI3.1415926其中,宏名用标识符表示,也就是前面讨论过的符号常量,上面示例中的PI就是宏名。正确使用“宏定义”的关键是宏调用时的“原样替换”。宏定义使用的简单示例。④宏定义不存在类型问题,它的参数也是无类型的。⑦宏定义允许嵌套。如:#defineN100#defineM2*N#defineK5+M⑧可以用#undef或不带替换字符串的宏定义终止宏定义的作用域。......
2023-11-20
不带参数的宏用指定标识符来代替一个字符串。其一般格式为:#define标识符 字符串例如:#define PI 3.1415926用标识符PI来表示3.1415926,这叫做宏定义。但多数人习惯把所有的宏定义都写在文件的前面虽然这不是必须的。一个宏定义后,就可以在程序中使用了,例如:这个函数返回圆的面积。这里的1、0与一般意义下的1、0形式上没有任何不同,不容易让人理解,有了宏,我们就可以很方便地解决这个问题了。......
2023-11-18
包括函数名的命名和类型说明、形式参数的类型说明、变量定义和语句。下面举例说明主函数和自定义函数。函数的定义是平行的,彼此相互独立,不能嵌套定义。函数的类型和函数返回值的类型应保持一致。以两个数求和为例,说明函数的定义。......
2023-10-21
“struct结构体名”为结构体数据类型名字,使用结构体类型名才能在程序中定义结构体变量。③“数据类型名结构体成员i;”指定了结构体类型中的一个结构体成员,结构体成员必须像以前的变量定义一样进行说明,成员名的命名规则与变量名相同,要符合标识符的命名原则。④结构体类型定义语句是一条完整的C语句,所以结构体类型的声明要用“;”作为结束符。......
2023-11-20
掌握选择结构的程序设计思想。完整的源程序:提醒:以上程序也可将case 2换成default,思考一下为什么?项目3:运输公司对用户计算运费。根据距离s的取值范围不同,折扣也相应发生变化,因此该程序为选择结构的程序,可以使用if语句,也可以使用switch语句。在编写程序时,距离s取值区间两端的数据都是250的整数倍,因此,可以通过s/250的方法将区间转换成用整型数据来表达,以便使用switch语句编写程序。......
2023-11-18
图5.3指针变量指针变量本身也是变量,所以指针变量在使用之前也需要定义。为指针变量赋值的方法有两种:一种是定义后,使用赋值语句的方式;另外一种是定义的同时进行初始化方式。......
2023-11-20
字符数组的初始化与一般数组的初始化类似,可以有完整赋值、部分赋值等情况。②使用字符串常量初始化字符数组。使用字符串常量对字符数组进行初始化时,系统会自动在末尾加上字符串结尾符号'\0',但定义的字符数组必须提供足够的长度。·如果没有指定字符数组的长度,系统自动指定为字符串常量中有效字符的个数+1。......
2023-11-20
相关推荐