2014-08-30 81 views
0

如果头文件不仅包含函数的原型,而且还包含完整的函数,那么在C中使用头文件有什么意义?我在linux源文件中发现了kdev_t.h文件,其中包含以下内容:为什么头文件包含完整的代码实现?

static inline dev_t new_decode_dev(u32 dev) 
    { 
     unsigned major = (dev & 0xfff00) >> 8; 
     unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00); 
     return MKDEV(major, minor); 
    } 

为什么.h扩展名? This问题涉及到C++中的类,但我不确定这里是否适用相同的原则。

+3

您可能会发现[**此问题及其接受的答案**](https://stackoverflow.com/questions/23699719/inline-vs-static-inline-in-header-file)一个有趣的阅读。 – WhozCraig 2014-08-30 12:10:59

+0

是的,它基本上和你的链接一样。 – mafso 2014-08-30 12:14:14

+0

谢谢@WhozCraig,这似乎是一个更清晰的解释。 – ssh 2014-08-30 12:16:41

回答

0

我没有任何来源,以支持我,但我认为这是由于以下原因的组合:

  1. 优化。它足够小,如果编译器可以使用完整的实现,它将使优化更容易。内核中经常会调用其中的一些小函数,这样分支的成本可以快速增加。在你的例子中,代码实际上只做了一些移位技巧 - 不值得保证对另一个目标文件的整个函数调用。虽然LTO等功能,我不确定这是相关的。
  2. 对于任何比单线更长的东西,宏是一种痛苦。有时编写一个单独的函数有点矫枉过正,但是这个任务太长,不适合一个(人类可读的)宏。宏也带着他们自己的一套头痛。功能提供了与宏相同的性能优势,但也保持了人的可读性。
  3. 空实现。内核是非常可配置的,你可以看到很多#ifdef的选项。有时候,如果一个内核函数被禁用,我们仍然希望这些函数是可调用的,但只是返回一个错误。这些空的实现最好放在头文件中而不是目标文件中,因此内核不必在源树中的每个C文件上运行编译器。换句话说,我们提高了编译时间。显然还有运行时优化,编译器可以事先知道死代码在哪里。

我认为上述三个原因的结合是Linux在头文件中放入一些小函数的原因。

相关问题