带参数的宏定义

带参数的宏定义
带参数的宏定义不仅要进行字符串的替换,而且还要进行参数替换,一般形式为:
#define <宏名>(<参数表>)<带参数的替换序列>
其中,参数为形参。
宏展开过程:程序中若有带实参的宏,则按#define指定的替换序列从左至右进行替换。若宏定义中包含有形参,则用程序中相应的实参替换形参,其中实参可以是常量、变量或表达式;若宏定义的替换序列中的字符不是形参,则在替换时保留。
[例7.2]从键盘输入两个数,输出较小的数。
#include “stdio.h”
#define MIN(a,b) ((a)<(b)?(a):(b))
main()
{
int x,y;
printf (“输入两个数”);
scanf (“%d,%d ”,&x,&y);
printf (“MIN=%d”,MIN(x,y));
}
以上程序执行时,用序列((x)<(y)?(x):(y))来替换MIN(x,y)。所以,可以输出两个数中的较小者。
对使用带参数的宏定义需要说明几点:
(1)对用宏定义定义的字符序列中的参数要用圆括号括起来,而且最好把整个字符串也用括号括起来,以保证在任何替换情况下都把宏定义作为一个整体,并且可以有一个合理的计算顺序,否则宏展开后,可能会出现意想不到的错误。如:
#define S(r) 3.14159* r* r
    …
area=S(a+b);
经过宏展开变为:
area=3.14159* a+b* a+b;
显然是由于在进行宏定义时,对r没有加括号造成与设计的原意不符。那么,为了得到形如:
area=3.14159* (a+b) * (a+b);
就应该在宏定义时给字符序列中的形参加上括号,如;
#define S(r) 3.14159* (r) * (r)
(2)宏定义时,不要在宏名与带参数的括号之间加空格,否则会将空格后的字符都作为替换序列的一部分。如:
#define S   (a,b) a* b
如果程序中有
mul= S(x,y)
则被展开为:
mul=(a,b)a* b(x,y)
(3)把函数和带参数的宏要区分开,虽然它们有相似之处,但它们是不同的,其区别见表7.1所示。
表7.1   函数和带参数之宏的区别
区    别 类              型
函   数 带参数的宏
是否计算实参的值 先计算出实参表达式的值,然后代替形参 不计算实参表达式的值,直接用实参进行简单的替换
何时进行处理、分配内存单元 在程序运行时进行值的处理、分配临时的内存单元, 编译时进行宏展开,不分配内存单元,不进行值的处理
类型要求 实参和形参要定义类型,且类型一致 不存在类型问题,只是一个符号表示,可以为任何类型
调用情况 函数的代码只作为一个拷贝存在,对程序较大、调用次数多的较合算,但调用函数时有一定数量的处理开销 在源代码中遇到宏定义时,都将其扩展为代码,程序调用几次宏就扩展为代码几次,但调用宏时没有处理的开销
 
函数和带参数的宏的区别:

1.函数调用时,先求出实参表达式的值,然后带入形参。而使用带参的宏只是进行简单的字符替换。
2.函数调用是在程序运行时处理的,分配临时的内存单元;而宏展开则是在编译时进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有“返回值”的概念。
3.对函数中的实参和形参都要定义类型,二者的类型要求一致,如不一致,应进行类型转换;而宏不存在类型问题,宏名无类型,它的参数也无类型,只是一个符号代表,展开时带入指定的字符即可。宏定义时,字符串可以是任何类型的数据。
4.调用函数只可得到一个返回值,而用宏可以设法得到几个结果。
5.使用宏次数多时,宏展开后源程序长,因为每展开一次都使程序增长,而函数调用不使源程序变长。
6.宏替换不占运行时间,只占编译时间;而函数调用则占运行时间(分配单元、保留现场、值传递、返回)。

一般来说,用宏来代表简短的表达式比较合适。

有时使用宏时会引起理解错误:

例:

#i nclude<iostream.h>
#define max(a,b) ((a>b)?a:b)
void main()
{
 int i=3,j=2;
 cout<<max(++i,j)<<endl;
 cout<<i<<"  "<<j<<endl;
}

运行结果:

5

5  2

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值