C语言中不同宏功能/内联方法的优缺点

时间:2009-10-15 10:01:35

标签: c macros inline

According to the C FAQ,基本上有3种用于在C中“内联”代码的实用方法:

#define MACRO(arg1, arg2) do { \
    /* declarations */ \
    stmt1;   \
    stmt2;   \
    /* ... */  \
    } while(0)    /* (no trailing ; ) */

#define FUNC(arg1, arg2) (expr1, expr2, expr3)

为了澄清这一点,参数在表达式中使用,逗号运算符返回最后一个表达式的值。

使用支持extension to gcc and in the c99 standardinline声明。

do { ... } while (0)方法在Linux内核中被广泛使用,但是如果有的话,我还没有经常遇到其他两种方法。

我指的是多语句“函数”,而不是像MAX或MIN这样的单语句。

每种方法的优点和缺点是什么,为什么在各种情况下选择其中一种?

3 个答案:

答案 0 :(得分:16)

谈到宏的具体用法,即充当“函数”的宏,我提到了内联函数中无法获得的宏的以下优点:

懒惰的参数评估。例如,像这样的宏

#define SELECT(f, a, b) ((f) ? (a) : (b))

将保留三元运算符的惰性参数计算属性:仅计算所选参数,而另一个则不计算。一个简单的内联函数模拟将提前评估两个参数,从而进行额外的不必要的工作。

访问上下文。宏可用于实现“本地函数”的某些相似性,即可访问局部变量和封闭函数参数的重复代码片段。

类型独立性(和类型参数)。宏允许您编写与类型无关的“函数”(参见上面的示例)。如果你不能摆脱类型依赖,你可以将类型作为参数传递给宏。

我作为专业人士提出的宏的上述属性可能被误用以导致重大失败(因此也可以作为缺点表示)。但这可以说是C中的许多语言特征。

答案 1 :(得分:5)

使用inline关键字的一个专家是通过函数原型检查参数的类型。使用宏你没有得到这样的东西,所以如果你把错误类型的东西放在其中,宏很容易产生奇怪的错误。 (尽管不像C ++中的模板错误那么可怕。)

使用宏的一个方面是你可以做一些像串联这样的时髦的东西,并使用#arg将宏参数转换为字符串。使用预处理器宏的另一个优点是,您可以使用cpp轻松检查它们如何展开以展开它们。这是你调试这些错误的方法。

宏定义函数的另一个有用之处在于,如果需要,可以将return语句粘贴到它们中以暂停父函数。使用内联函数,您必须返回一个值,然后检查返回值。

答案 2 :(得分:0)

我在使用任何构造时可以看到的唯一专业是使代码更快。

因此,选择一种能够提供最快代码的方法!

如果它完全相同,那么我发现它更清晰

  1. '标准'功能
  2. 一个inline函数
  3. #define ... do {} while(0)方法
  4. 带逗号分隔表达式的宏