写出来代码和写的优秀的代码是两回事,我们经常可以看到别人写的优秀的代码,比如有些部分为什么使用宏而不使用函数,有些部分使用内敛而不是用宏等等。
今天就来总结下。
目录
一。宏定义函数和函数的区别
二。宏定义和内敛函数inline
1.const.
2.enum.
3.inline.
一.宏定义函数和函数的区别
在c语言中,用宏定义函数和函数的区别
1.宏定义函数没有参数检验
比如:
#define Max(a, b) a>b? a : b
传参数的时候我们一定要注意类型
2.代码编译生成的指令不同
宏定义没有调用和传参指令,多的是每次调用都会编译生成一个类似的函数体
3.宏定义函数应当尤其注意括号问题
括号问题很重要,尤其当参数是表达式的时候,所以我们能添加括号的地方就添加括号
4.注意参数是表达式的问题
参数是表达式括号一定要带上
参数是表达式时有可能会多计算表达式
5.一些宏函数会导致底的代码执行效率
举个简单的例子,有些宏函数可能会重复计算, 不但会出错也会导致效率降低
#define Max(a, b) a > b ? a : b
Max(++a, ++b)
结果是++a > ++b ? ++a : ++b
但是宏定义函数看起来像函数,但是却不会引起函数调用引来的额外开销。
所有宏函数在c里有好处,但是也要注意使用,最好(一定)避免表达式传参。
二.宏定义和内敛函数inline
我们说说c++中宏定义的问题, 因为C++中多了内敛函数
effect c++ 条例二是:尽量以const, enum, inline替换#define
1.const
举个例子hello.c
在编译阶段,首先执行的是预处理阶段,预处理阶段hello.c被修改为hello.i(文本), 预处理器根据#开头的命令来修改原始的c程序。
比如宏定义一个常量,我们#define Max 100
开始预处理器时可能会移除#define 宏定义, 而在编译阶段就如果Max没进入记号表,那么当你使用这个常量时出现错误可能提醒就是100而不会提到Max。你肯定会为此感到差异,一位一般宏定义都在头文件中,
建议使用const 来定义常量
我们来看看差别
同样是头文件中,我们发现define 并没有提到是什么出问题了,相反const 确提出了Max是read_only的,在很大的程序中如果出这样的错可能会很头疼。。。
!!前提说明,用const修饰的变量作为数组的大小在c++中不会报错的, 并且c++也支持这样做, 但是在c中就会报错,c中只有常量表达式才能作为数组的大小,这点一定要记住!!
c中用enum是个不错的选择。但是注意,枚举元素都有一个默认值,是从0开始, 当然我们可以指定它们的值。
2.enum
举个c++例子
const Min 10
enum { Max = 100 };
int a[Max];
int b[min];
&Min合法, &enum是违法的,会报错。
那么我们可以发现,当我们不想让他人用指针或者引用来修改这个数据时,就可以用enum来实现这个约束。
3.内敛函数
我们来说说内敛函数,内敛函数存在于c++中,内敛函数的声明前面要添加inline关键字。但注意以下几点:
<1. 在类中定义的函数默认为内敛函数,但是当函数中存在循环,递归,开关语句,代码量大于5行左右会被认为是普通函数。
<2.内敛函数必须和函数体一起声明才有效。
例如 inline int fun(int i ); //不是内敛函数
inline int fun(int i ) { return i*i }; //内敛函数
<3.内敛函数的定义必须出现在第一次调用之前
<4.将读写成员函数定义为内敛函数将会获得较好的效率,因为读写成员函数会经常调用。。
<5.内敛函数有参数检查机制
宏定义函数的缺点上面已经有了。想对比于宏定义函数,内敛函数是真正的函数!它有参数检查机制,它可以调试,它没有上述那么多缺点。
那么对比于普通函数,内敛函数没有普通函数的参数压栈,生成汇编里面call调用,返回参数,执行return, 普通函数调用时首先立即保存现场->跳转到执行的调用函数->执行->返回保存的地址继续执行。
内敛函数是将函数体嵌入到每一个调用处,实行类似宏定义那样。所以简短的1-5行代码执行效率是非常高的
最后我们在看一下宏和函数的汇编代码吧(我也不懂汇编,但从汇编代码量可以看出来)
左边为宏定义,右边为函数,可见宏定义在开始就被预处理器移走了,所以没有宏定义的代码。
但从汇编我们可以看出宏定义在简短代码调用的好处。
总结:
c语言中我们一般使用define宏定义,(为什么不使用内敛,内敛函数在c99标准才加入,有的编译器不支持,这大概就是鲁棒性把 - -)。
c++中我们使用inline内敛函数代替宏定义,包括使用const 和 enum类替换宏定义