根据C FAQ,基本上有3种用于在C中"内联"代码的实用方法:
#define MACRO(arg1, arg2) do { \
/* declarations */ \
stmt1; \
stmt2; \
/* ... */ \
} while(0) /* (no trailing ; ) */
Run Code Online (Sandbox Code Playgroud)
要么
#define FUNC(arg1, arg2) (expr1, expr2, expr3)
Run Code Online (Sandbox Code Playgroud)
为了澄清这一点,参数在表达式中使用,逗号运算符返回最后一个表达式的值.
要么
使用inline
支持作为gcc扩展和c99标准的声明.
该do { ... } while (0)
方法在Linux内核中被广泛使用,但是我还没有经常遇到其他两种方法.
我指的是多语句"函数",而不是像MAX或MIN这样的单语句.
每种方法的优点和缺点是什么,为什么在各种情况下你会选择一种方法呢?
AnT*_*AnT 16
谈到宏的特定用途,即充当"函数"的宏,我提到了内联函数中无法获得的宏的以下优点:
懒惰的论据评估.例如,像这样的宏
#define SELECT(f, a, b) ((f) ? (a) : (b))
Run Code Online (Sandbox Code Playgroud)
将保留三元运算符的惰性参数评估属性:仅评估所选参数,而不评估另一参数.直接的内联函数模拟将提前评估两个参数,从而进行额外的不必要的工作.
访问上下文.宏可以用于实现"局部函数"的一些相似性,即可以访问局部变量和封闭函数的参数的重复代码片段.
键入独立性(和类型参数).宏允许您编写与类型无关的"函数"(参见上面的示例).如果你无法摆脱类型依赖,你可以将类型作为参数传递给宏.
我作为专家提出的宏的上述属性可能被误用以导致重大失败(因此也可以作为缺点表示).但这可以说是C语言中的许多语言特征.
小智 5
使用inline关键字的一个专家是通过函数原型检查参数的类型.使用宏你没有得到这样的东西,所以如果你把错误类型的东西放在其中,宏很容易产生奇怪的错误.(尽管不像C++中的模板错误那么可怕.)
一个使用宏的专家是你可以做一些时髦的事情,如连接,并使用#arg将宏参数转换为字符串.使用预处理器宏的另一个优点是,您可以使用cpp轻松检查它们如何展开以展开它们.这是您调试这些错误的方法.
宏定义函数的另一个有用之处在于,return
如果需要,可以将语句粘贴到它们中以暂停父函数.使用内联函数,您必须返回一个值,然后检查返回值.