是否有任何标准来确定是否在linux内核中通过内联或宏实现函数?

时间:2013-01-05 10:32:32

标签: c linux linux-kernel

在linux内核源代码中,我发现很多函数都采用内联形式实现的小体,还有很多其他函数也是用MACRO实现的小体。

所以我想知道在选择哪一个时所涉及的考虑是什么,因为我认为两者都是合适的。或者这只是个人风格?

3 个答案:

答案 0 :(得分:1)

宏不进行类型检查并需要其他特殊注意事项(即只计算一次表达式),因此应尽可能避免使用它们。但是,不检查类型的优点是允许您在C89中编写通用函数。

同样编写真正的inline函数允许(使用可以在内核配置中激活的某个标志)编译器如果具有性能优势也可以取消内联,而对于宏来说这是不可能的,简单的文字替换。

答案 1 :(得分:0)

宏是文本替换可以比内联函数做更多。它们也可能有不良副作用。考虑众所周知的交换宏。

#define SWAP(a,b) {int t=a; a=b; b=t}

并注意到SWAP(i,t[i])做了不想要的事情。

内联函数的优点是具有类似语义的函数调用(参数被评估一次,等等......)。

所以这主要是编码风格,并认识到宏和&功能是不同种类的动物。

你的问题与内核没有特别的关系。任何C(甚至C ++)程序都有同样的问题。

答案 2 :(得分:0)

请记住,Linux内核中的很多代码已存在很长时间了。一些宏也对输入/环境的其他部分做了“聪明的东西”,而不是函数将/可能/应该做什么。

作为一般规则,尽可能使用(内联)函数,因为如上所述,函数的“陷阱”较少。

如果你做了聪明的替换或其他一些“只能在宏中做”,如果可能的话,最好制作一个形成函数参数的宏。例如。

#define ASSERT(x)  do { if (!(x)) { fprintf(stderr, "Assertion failed on %s:%d", __FILE__, __LINE__); exit(1); } while(0);

可以完成:

#define ASSERT(x) do_assert(!!(x), __FILE__, __LINE__);

void do_assert(bool val, const char *file, int line)
{
    if (!val)
    {
        fprintf(....);
        exit(1);
    }
}

现在,您可以在调试版本中,在if中的断言中设置断点,并且每当断言失败时,您都可以看到如何到达那里。使用宏,这是不可能的。

现代编译器在适当的情况下很好地内联,只有一半的机会。