我想知道内联函数和宏函数之间的区别。
1)内联函数是否与宏函数相同?
2)我知道两者都没有被调用,但它们在编译阶段被其代码所取代。不是吗?
3)如果有差异,你能指定它吗?
答案 0 :(得分:23)
内联用函数体替换对函数的调用,但是,内联只是编译器的请求可以忽略(你仍然可以将一些标志传递给编译器强制内联或使用gcc的 always_inline 属性。
另一方面,宏在编译之前由预处理器扩展,所以它就像文本替换一样,宏也不是类型检查,内联函数是。 wiki中有一个比较。
为了完整起见,您仍然可以使用gros的某种类型的安全性,例如,使用gcc的__typeof__
,以下代码生成几乎相同的代码,如果使用错误的类型,都会导致警告:
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
__attribute__((always_inline)) int max(int a, int b) {
return (a > b ? a : b);
}
注意:有时无格式的宏只是需要的东西,例如,看看uthash如何使用宏来使任何C结构可以在不使用强制转换的情况下进行清理。
答案 1 :(得分:19)
1)否。
2)C中的宏只是在编译器处理源代码之前扩展的文本。 inline关键字用作编译器的提示,函数可以内联放置而无需设置调用堆栈。
所以,例如,假设您有以下两段代码(首先是宏,然后是内联函数):
#define MAX(x,y) (x > y ? x : y)
和
inline int max(int x, int y) { return x > y ? x : y; }
当预处理器在您的代码中找到以下调用时:
int highest = MAX (var_1, var_2);
用
替换它int highest = (var_1 > var_2 ? var_1 : var_2);
以上是编译器在编译过程中最终获得的内容,因此MAX(x,y)定义的片段是MAX的替换(var_1,var_2)。当编译器找到函数调用
时int highest = max (var_1, var_2);
然后调用函数“max”。你必须假设它被称为正常方式,因为编译器可以自由地忽略你的“内联”提示并且对该函数的调用通过普通的调用栈而不是简单地将函数的代码放在它所在的位置。遇到。
对宏的最后一点警告:因为它是所有文本替换而不是代码替换,如果你这样做:
int highest = MAX (v1++, v2++);
预处理器会将其扩展为:
int highest = (v1++ > v2++ ? v1++ : v2++);
这可能不是你想要的。
答案 2 :(得分:6)
宏是由预处理器替换的声明(在实际的编译之前)根本不是函数。在实际的编译阶段开始之前,宏已经很久了,剩下的就是它们的扩展(包括扩展为空)。
内联函数实际上是符合语言的函数,具有范围规则,变量声明,逻辑结构(循环等)等。内联函数不像宏那样扩展到编译前步骤。它们像常规代码一样编译,但可以将其注入(缺少更好的术语)到编译代码中并根据需要进行优化。
答案 3 :(得分:1)
没有inline
与macro
定义不同,因为宏是预先处理的,但内联只是指示编译器将函数的整个主体放在调用它的位置。
在任何函数定义之前放置inline关键字只是指示或请求,编译器可以自由选择是否将该函数内联或保持正常
宏替换:preprocessing phase
(即编译前)
- 在linux test.c
test.i
结果文件
内联替换:compilation phase