25

可能重复:
内联函数与预处理器宏

我想知道内联函数和宏函数的区别。

1)内联函数和宏函数一样吗?

2)我知道两者都没有被调用,但它们在编译阶段被其代码替换。不是?

3)如果有区别,你能指定吗?

4

4 回答 4

38

内联用函数的主体替换对函数的调用,但是,内联只是对编译器的一个可以被忽略的请求(您仍然可以将一些标志传递给编译器以强制内联或使用带有 gcc 的always_inline属性)。

另一方面,宏在编译之前由预处理器扩展,所以它就像文本替换一样,宏也不是类型检查,内联函数是。维基上有一个比较。

为了完整起见,您仍然可以使用宏具有某种类型的安全性,__typeof__例如使用 gcc,以下代码生成几乎相同的代码,并且如果与错误的类型一起使用都会导致警告:

#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 结构可散列化,而无需借助强制转换。

于 2012-11-14T08:36:10.847 回答
31

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++);

这可能不是你想要的。

于 2012-11-14T09:04:29.453 回答
6

宏是由预处理器(在实际编译之前)替换的声明,它们根本不是函数。在实际编译阶段开始之前,宏早已不复存在,剩下的就是它们的扩展(包括扩展为空)。

事实上,内联函数是符合语言的函数,具有范围规则、变量声明、逻辑构造(循环等)等等。内联函数不像宏那样在预编译步骤中扩展。它们像常规代码一样被编译,但随后可以注入(因为没有更好的术语)到编译后的代码中并根据需要进行优化。

于 2012-11-14T08:40:47.203 回答
1

inlinemacro定义不同,因为宏是预处理的,但内联只是指示编译器将函数的整个主体放在调用它的位置。

将 inline 关键字放在任何函数定义之前只是指示或请求,编译器可以自由选择是使该函数内联还是保持正常

宏替换:(preprocessing phase即编译前)

test.c--在linux中输入文件结果文件test.i

内联替换:compilation phase

于 2012-11-14T08:38:33.040 回答