C语言【宏定义与函数的区别】

       在代码开发过程中,有一些常用或者可以通用的功能或者代码段,实现这些功能,既可以写成函数,也可以封装成为宏定义。那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍。

先看宏

        宏: #define 机制包括了一个规定,允许把参数替换到文本中,这种实现常常称为宏,或者宏定义。

 

宏对变量的副作用:

#define SQUARE(x)  (x * x)     //常见的求平方

然后求平方

SQUARE(5)

预处理器就会用  5 * 5 这个表达式替换上面的表达式,结果是 25,符合你的预期。

但是请看下面一个:

int a = 5;
printf(" (5 + 1) square: %d\n", SQUARE( 5 + 1));
结果是:11    不符合你的预期

实际在执行时, 使用 5 + 1 * 5 + 1 替换了上面的表达式, 结果就是11, 不符合你的预期, 这种是最常见的相邻的操作符优先级, 大于你传入参数需要优先执行操作符的优先级.
类似的还有 a++ 这样的操作, 都会带来副作用.

宏对参数的副作用,在使用自定义函数时就不会产生:

int get_square(int a)
{
    return a*a;
}

调用 get_square(5+1)时, 不会产生参数的副作用, 程序执行时, 会先算出5+1的和, 然后再传入函数去执行。

 

 

先看一下《C与指针》中的宏定义“函数”与自定义接口的区别:

 宏与函数的区别
属性#define 宏函数
代码长度

每次调用时,宏代码都会被插入到程序中。除了非常小的宏之外,程序的长度将大幅增加

函数代码只出现在一个地方,每次调用这个函数时,调用的都是那个地方的同一份代码
执行速度更快存在函数调用/返回的额外开销
操作符优先级

宏参数的求值是在所有周围下上文环境里,除非给它们加上括号,否则邻近操作符的优先级,可能会产生不可预测的结果

函数参数只在函数调用时求值一次,它的结果值传递给函数。表达式的求值更容易预测。

参数求值

参数每次用于宏定义时。它们都将重新求值,由于多次求值,具有副作用的参数可能会产生不可预料的结果。

参数在函数被调用前只求值一次,在函数中多次使用参数,并不会导致多种求值过程,参数的副作用并不会造成任何特殊问题

参数类型宏与类型无关,只要参数的操作是合法的,它可以适用于任何参数类型

函数的参数是与类型有关的,如果参数的类型不同,就需要使用不同的函数,即使它们的任务是相同的

我们常用到的比较大小,宏定义:

#define MAX( a, b) ( (a) > (b) (a) : (b) )

自定义接口实现就是:

int max( int a, int b)
{
    return (a > b a : b)
}

区别:

1. 最直观的来讲,自定义的函数已经指定了类型,只能比较两个整数的大小,却不能再去比较浮点数的大小,或者两个ASCII码的大小;而宏定义是不会限定类型的,只要比较的类型一致即可。

2. 自定义接口在程序运行时,会产生临时的堆空间,有临时的空间消耗,如果是递归的话,需要的临时栈空间可能更多;宏定义是在程序运行时,会将宏定义这段代码插入到程序中执行,会有额外的代码段。

3. 自定义接口在调用时,实际的开销要比代码段大,规模更大; 而宏比自定义函数在程序的规模和速度方面,比自定义函数更胜一筹。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值