c语言中带参数的宏的运算,简单分析带参数宏定义

相信学过C语言的同学都对C语言中的宏定义有一定的了解,而在实际编写程序时往往程序员都会加入带参数的宏,那么究竟什么是带参数的宏定义呢?下面课课家笔者就为大家介绍C语言中带参数的宏定义。

ec2636357ae078724b1f3ce03495eafa.png

在C语言中,通常允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数,这方面和函数有些类似。对带参数的宏,我们在调用中的时候不仅要宏展开,而且要用实参去代换形参。带参宏定义的一般形式为:#define宏名(形参列表)字符串。从字符串中我们可以看到含有各个形参。带参宏调用的一般形式为:宏名(实参列表);。具体代码例子如下:

#defineM(y)y*y+3*y//宏定义

//Code

k=M(5);//宏调用

在我们进行宏调用时,用实参5去代替形参y,经预处理宏展开后的语句为k=5*5+3*5。下面笔者以输出两个数中较大的数的代码例子为例给大家讲解。

#include

#defineMAX(a,b)(a>b)?a:b

intmain(){

intx,y,max;

printf("inputtwonumbers:");

scanf("%d%d",&x,&y);

max=MAX(x,y);

printf("max=%d\\n",max);

return0;

}

输出结果:

inputtwonumbers:1020

max=20

从上面的代码例子中我们可以观察到,程序第2行进行了带参宏定义,用宏名MAX表示条件表达式(a>b)?a:b,形参a、b均出现在条件表达式中。程序第7行max=MAX(x,y)为宏调用,实参x、y将代换形参a、b。宏展开后该语句为:

max=(x>y)?x:y;

下面是笔者对带参宏定义的简单总结:

①在带参宏定义中,形参之间可以出现空格,但是宏名和形参列表之间不能有空格出现。比如把:#defineMAX(a,b)(a>b)?a:b写为:#defineMAX(a,b)(a>b)?a:b将被认为是无参宏定义,宏名MAX代表字符串(a,b)(a>b)?a:b。宏展开时,宏调用语句:max=MAX(x,y);将变为:max=(a,b)(a>b)?a:b(x,y);,这很明显是错误的。

②在带参宏定义中,不会为形式参数分配内存,因此不必指明数据类型。相反在宏调用中,实参包含了具体的数据,要用它们去代换形参,因此必须指明数据类型。在函数中,形参和实参是两个不同的变量,都有自己的作用域,调用时要把实参的值传递给形参;而在带参数的宏中,只是符号的替换,不存在值传递的问题。下面笔者以输入n,输出(n+1)^2的值作为代码例子来给大家说明:

#include

#defineSQ(y)(y)*(y)

intmain(){

inta,sq;

printf("inputanumber:");

scanf("%d",&a);

sq=SQ(a+1);

printf("sq=%d\\n",sq);

return0;

}

输出结果:

inputanumber:9

sq=100

从上面的代码例子中我们可以观察到,第2行为宏定义,形参为y。第7行宏调用中实参为a+1,是一个表达式,在宏展开时,用a+1代换y,再用(y)*(y)代换SQ,最后会得到语句:sq=(a+1)*(a+1);。这与函数的调用是不同的,函数调用时要把实参表达式的值求出来再传递给形参,而宏展开中对实参表达式不作计算,直接按照原样替换。

③在宏定义中,字符串内的形参通常要用括号括起来以避免出错。比如上面的宏定义中(y)*(y)表达式的y都用括号括起来,因此结果是正确的。若是去掉括号把程序改为以下形式, 输出结果就会改变 :

#include

#defineSQ(y)y*y

intmain(){

inta,sq;

printf("inputanumber:");

scanf("%d",&a);

sq=SQ(a+1);

printf("sq=%d\\n",sq);

return0;

}

输出结果为:

inputanumber:9

sq=19

同样我们是输入9,但得到的结果却是不一样的。原因在于替换只作符号替换而不作其它处理而造成的。宏替换后将得到以下语句:sq=a+1*a+1;。由于a为9故sq的值为19。这显然与原本的目标相违背,因此参数两边的括号是不能少的。另外即便在参数两边加括号还是不够的,其结果也是和原本输出的结果也不一样。具体大家可以观察下面的代码例子:

#include

#defineSQ(y)(y)*(y)

intmain(){

inta,sq;

printf("inputanumber:");

scanf("%d",&a);

sq=200/SQ(a+1);

printf("sq=%d\\n",sq);

return0;

}

相比于前面的代码,这里只是把宏调用语句改为:sq=200/SQ(a+1);。在我们运行程序后,正常情况下在输入9的结果为2。但实际上根据以上代码例子输入后所得到结果并非如此,其结果最终会如下所示:

inputanumber:9

sq=200

我们不妨来分析宏调用语句,在宏展开之后变为:sq=200/(a+1)*(a+1);。a为9时,由于“/”和“*”运算符优先级和结合性相同,所以先计算200/(9+1),结果为20,再计算20*(9+1),最后得到200。所以我们为了得到正确答案,应该在宏定义中的整个字符串外加括号:

#include

#defineSQ(y)((y)*(y))

intmain(){

inta,sq;

printf("inputanumber:");

scanf("%d",&a);

sq=200/SQ(a+1);

printf("sq=%d\\n",sq);

return0;

}

综上所述,对于带参宏定义不仅要在参数两侧加括号,我们还应该在整个字符串外加括号,这点是值得大家要去注意的地方!

本次简单分析带参数宏定义的教程到此就暂告一段落了,如果以后有内容的补充或者修改的话笔者会继续在此补充或者修改,同时也欢迎大家对此教程提出建议和补充。最后希望这次的教程对大家学习C语言能起到一定的帮助作用!

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值