在 C 语言中,对于一些常用或通用的功能或代码段的封装可以有两种方式:函数和宏定义。那么,对于这两种方式,我们该如何抉择呢?在解决这个问题之前,有必要先来了解一下它们之间的区别。
1) 从程序的执行来看
函数调用会带来额外的开销,它需要开辟一片栈空间,记录返回地址,将形参压栈,从函数返回还要释放栈。这种开销不仅会降低代码效率,而且代码量也会大大增加。而宏定义只在编译前进行,不分配内存,不占运行时间,只占编译时间,因此在代码规模和速度方面都比函数更胜一筹。
2) 从参数的类型来看
函数的参数必须声明为一种特定的数据类型,如果参数的类型不同,就需要使用不同的函数来解决,即使这些函数执行的任务是相同的。而宏定义则不存在着类型问题,因此它的参数也是无类型的。也就是说,在宏定义中,只要参数的操作是合法的,它可以用于任何参数类型。
3) 从参数的副作用来看
毋庸置疑,在宏定义中,在对宏参数传入自增(或者自减)之类的表达式时很容易引起副作用,尽管前面也给出了一些解决方案,但还是不能够完全杜绝这种情况的发生。与此同时,在进行宏替换时,如果不使用括号完备地保护各个宏参数,那么很可能还会产生意想不到的结果。除此之外,宏还缺少必要的类型检查。而函数却从根本上避免了这些情况的产生。
4) 从代码的长度来看
在每次使用宏时,一份宏定义代码的副本都会插入程序中。除非宏非常短,否则使用宏会大幅度地增加程序的长度。而函数代码则只会出现在一个地方,以后每次调用这个函数时,调用的都是那个地方的同一份代码。