文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C语言中宏和函数的区别有哪些

2023-07-05 23:04

关注

这篇文章主要介绍了C语言中宏和函数的区别有哪些的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言中宏和函数的区别有哪些文章都会有所收获,下面我们一起来看看吧。

C语言中的宏和函数是非常相似的,它们都可以完成类似的功能。比如,想要求2个数的较大值,使用宏的写法是:

// 宏的定义#define MAX(x, y) ((x)>(y)?(x):(y))// 使用int m = MAX(10, 20);

使用函数的写法是:

// 函数的定义int Max(int x, int y){return x>y ? x : y;}// 使用int m = Max(10, 20);

既然宏和函数长的那么像,究竟什么时候用宏,什么时候用函数呢?这就要了解一下它们之间的区别了。我总结了他俩之间的区别,主要体现在以下几点:

代码长度。

执行速度。

操作符优先级。

带有副作用的参数。

参数类型。

调试。

递归。

命名约定。

其他。

1.代码长度

宏会在每个使用它的地方替换。比如前面提到的求两个数的较大值的宏,假设这么使用:

int m = MAX(10, 20);// ...m = MAX(20, 30)// ...m = MAX(30, 40);// ...// ...

每个使用宏的地方都会被替换掉。

int m = ((10)>(20)?(10):(20));// ...m = ((20)>(30)?(20):(30))// ...m = ((30)>(40)?(30):(40));// ...// ...

这里的宏体比较短,所以替换进去后,代码的长度并没有明显的提升。但是,假设这个宏有100行代码,每个地方展开后,展开3次,就会多出300行代码。如果更加频繁的调用,调用100次,就会多出10000行代码。所以,当宏体比较长,尤其是调用次数还比较多的情况下,会导致代码长度大大增加。

而函数就不存在这个问题,函数不管调用几次,都只需要写一次函数的代码,每次使用时直接调用即可,代码长度是可控的。

2.执行速度

函数调用时,需要在栈空间上开辟一块栈帧,参数还要压栈。当函数体的代码执行完后,需要返回时,还要销毁栈帧。这些都是有开销的,执行速度较慢。

但是,宏的代码在预处理阶段就已经完成替换,不存在这个问题,执行速度较快。

3.操作符优先级

使用宏时,代码是在对应的位置直接展开,如果该位置周围有其他操作符,有可能干扰宏体内的操作符的执行顺序,导致错误的结果。比如:

#define DOUBLE(x) x+x

如果这么调用:

int ret = 2 * DOUBLE(10);

我们想的是:DOUBLE(10)会算出20,再乘2,得到40。然而,实际代码会这样展开:

int ret = 2 * 10+10;

由于乘号的优先级比较高,会先算2*10,得到20,再加10得到30,和预期的结果不一致。

但函数不存在这个问题。

int Double(int x){    return x+x;}

当这样调用时:

int ret = 2 * Double(10);

一定是先把10传给函数,函数计算完后返回20,再进行别的计算。

当然,如果参数本身是表达式时,也会有相同的问题。比如:

#define SQUARE(x) x*xint Square(int x){    return x*x;}int ret1 = SQUARE(3 + 2);int ret2 = Square(3 + 2);

函数就是正常的,先计算3+2得到5,在把5传参,得到25。但是宏会这样替换:

int ret1 = 3 + 2*3 + 2;

由于乘号的优先级较高,得到的结果就是11,和预期结果不符。

为了解决这样的问题,建议写宏时多加括号,防止受到其他操作符的影响。比如:

#define DOUBLE(x) ((x)+(x))#define SQUARE(x) ((x)*(x))

4.带有副作用的参数

对于MAX宏,如果这样使用:

int x = 3;int y = 5;int m = MAX(x++, y++);

我们的想法是:把x和y传参,算出x和y的较大值为5,即m应该是5,而后置++会把x和y的值分别改成4和6。但是实际替换时是这么替换的:

int m = ((x++)>(y++)?(x++):(y++));

计算时,先判断x++>y++这个表达式,显然x<y,故为假,判断完后x和y都要++,x改成4,y改成6,返回y++的结果,即6,y再++改成7。所以最终结果是:m为6,x为4,y为7,和预期不符,原因是带有副作用的宏参数影响了结果。

函数就不存在这个问题。如果调用Max函数:

int x = 3;int y = 5;int m = Max(x++, y++);

由于函数的传参和函数体代码的执行是分开的,所以结果和预期相同,m=5, x=4, y=6。

5.参数类型

宏是直接对代码进行文本替换,是不检查类型的。比如:

int m1 = MAX(3, 5);// 会被替换成int m1 = ((3)>(5)?(3):(5));double m2 = MAX(3.2, 5,3); // 会被替换成double m2 = ((3.2)>(5.3)?(3.2):(5.3));

但是函数的形参是有类型的,传参时会对类型进行检查。比如前面的Max函数,参数列表是(int, int),只能求2个整数的较大值,如果要求两个浮点数的较大值,是无能为力的。

6.调试

宏直接完成代码的替换,不方便调试。因为宏的替换在预处理阶段已经完成,但是调试时调试的是最终生成的可执行程序。由于已经完成了替换,看到的代码和调试的代码是不一样的。函数就没有这个问题,可以逐语句调试。

7.递归

宏不能递归,函数可以实现递归。

8.命名约定

一般宏的名字为全大写,函数名不会全大写。比如:

宏名:MAX, DOUBLE, SQUARE。

函数名:Max, Double, Square。

但是也有例外。比如库中的offsetof是一个宏,而不是函数。

关于“C语言中宏和函数的区别有哪些”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“C语言中宏和函数的区别有哪些”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯