宏函数并不是真正意义上的函数,宏函数是一种在预处理阶段进行文本替换的机制。宏函数是被#define关键字定义来修饰的函数。内联函数是被inline关键字来修饰的函数,内联函数是在一种在编译阶段才内联展开的函数,需要注意的是,编译器并不会把所有内联函数的函数定义部分都展开,具体是否展开取决于编译器的优化策略与具体情况。
1.宏函数
宏函数定义格式:
#define 函数名(参数列表) 表达式
如:define ADD(a,b) ((a)+(b))
gcc maic.c编译结果:
a = 24
mian.i是预处理文件,可以看到,在预处理文件mian.i中,main函数中调用的PRODUCT(2+2, 3+3)被替换成了(2+2)*(3+3) ,需要注意的是宏函数的表达式部分必须用括号括起来,避免优先级的问题,当没有用括号括起来时:
可以看到,当宏定义(宏函数)的表达式部分没有用括号括起来时,在预处理阶段生成的main.i文件中,main函数调用的PRODUCT(2+2, 3+3)被替换成了2+2*3+3,宏定义(宏函数)的表达式部分没有用括号括起来,因优先级问题,编译后的结果自然也就会产生差异。
gcc main.c编译结果:
a = 11
可以看到,编译结果确实产生了差异,因此,在定义宏函数时,为了避免优先级的问题,宏函数的表达式部分必须用括号括起来。
2.内联函数
被inline关键字声明的函数称为内联函数,内联函数是在编译时展开的函数
可以看到,在main.i预处理文件中,宏函数被(2+2)*(3+3)展开替换了,内联函数并没有被展开替换, 当我们再进入编译阶段生成的汇编文件main.s查看时:
当我们把inline关键字去掉后,再编译出汇编文件main.s查看时:
可以看出,内联函数是在编译时直接把函数定义部分嵌入到调用位置的,因此内联函数可以减少函数调用的开销,提高程序的运行效率。
需要注意的是内联函数的代码不能过长,因为内联函数省去函数调用次数是以代码膨胀为代价的,内联函数不能包含循环语句和递归函数,因为循环语句和递归函数要比函数调用的开销大。
总结:
在C语言中,宏函数与内联函数主要有一下区别
1.宏函数并不是函数,内联函数是函数;
2.宏函数是在预处理阶段展开的宏替换,内联函数是在编译阶段,因此内联函数有类型安全检查,宏函数没有。