2012-02-24 70 views
20

我有一些在.h文件中定义的小函数。这是一个小型项目(现在),我想避免声明和定义分开的痛苦,因为它们一直都在变化。为了避免多重定义的符号,我可以让他们staticinline。什么应该是首选,为什么?在头文件中定义的小函数:内联还是静态?

我知道在头文件中定义函数通常是不好的做法。你不必在答案中提到,这个问题在技术上意味着。

+1

**在**头文件中实现它们是不好的,而不是定义它们;) – m0skit0 2012-02-24 09:40:39

+0

C/C++中头文件的思想为开发人员创造了额外的工作,我知道没有人想要复制代码大小小的声明 – linquize 2012-02-24 09:42:44

+1

或者它的功能很小:D? – UmNyobe 2012-02-24 09:43:31

回答

22

我会用static inline,但static也可以。

externextern inline都出来了,因为如果头被包含在一个以上的翻译单元,你会得到多个外部定义,所以你需要考虑staticstatic inlineinline规范。

Heptic在他的答案正确地指出,大多数编译器考虑功能无论是否指定inline的或不内联,即inline的主要影响是其对联动效应。

但是,static定义有内部联系,所以staticstatic inline之间没有太大的区别;我更喜欢static inline在纯粹的文体原因的头文件中的函数定义(经验法则:头文件应该只包含extern声明,static const变量定义和static inline函数定义)。

inline而不staticextern导致一个直列定义,其标准状态(C99 6.7.4,§6)

提供到外部的定义,其中转换器可用于替代执行 对同一个翻译单元中的函数的任何调用。不确定对 函数的调用是使用内联定义还是外部定义。

即内联定义应该总是伴随着外部定义,这不是你正在寻找的。

有关C99内联语义的细微之处的更多信息,请参见this answerClang homepageC99 Rationale (PDF)

请记住,如果有-std=c99-std=gnu99存在,GCC将只使用C99语义...

+0

@Heptic:标准的措辞有点含糊不清,但据我了解,编译器总是可以自由地完全忽略任何内联定义并回退到外部定义,如果没有这样的定义,这显然会失败在另一个翻译单位中...... – Christoph 2012-02-24 12:19:02

+0

@Heptic:我的解释似乎是正确的 - 请参阅随附的示例,即C99 7.6.4§8 – Christoph 2012-02-24 12:21:51

+0

@Heptic:另外,并非所有主要编译器/链接程序都以您描述的方式工作 - 此外如果'-std = c99'或'-std = gnu99'存在,gcc也尊重C99的语义...... – Christoph 2012-02-24 12:48:58

0

我觉得静态连续是去要内联函数的方式,只有静态对于那些你不想要的。

静态指能见度,但直列是不明确的关于标准(C99)的可见性。无论如何,这不是它的目的:内联用于内联函数,因此它从您可能不想要的可见性角度来看具有副作用。

+0

你忽略解释为什么。 – 2012-02-24 09:54:44

+0

“内联模糊不清,并允许使用外部关键字,从而破坏了您的目的。” – m0skit0 2012-02-24 09:59:52

+0

我扩大了我的解释,希望你可以评论当你downvote,所以我(我们)可以学习;) – m0skit0 2012-02-24 13:44:35

3

由于问题是关于C(不是C++),inline意味着

  1. 你希望“调用该函数是尽可能快地”(ISO9899-1999,6.7.4(5 ))。同一段也指出,这个建议在何种程度上是有效的。换句话说,它几乎没有影响,并不意味着任何内联(事实上,由于指令缓存效应,非内联可能会更快)。
  2. 有一些限制和特殊情况结​​合extern(ISO9899-1999,6.7.4(6),例如inline功能可按具有外部链接必须在相同的编译单元所定义,并且一个直列定义允许一个extern定义在其他地方没有错误(这并不一定是好事,因为这两个功能不需要在功能上等同,它是不确定哪一个编译器使用在任何时间!)。

链接器的影响由Heptic给出的是C++所需要的,但C不要求(据我所知),它们必然是由“应在ISO14882,7.1.2(4)中的所有翻译单元“条款”中具有相同的地址。我不知道C99中有类似的条款。
但是,由于完全不同的语言C和C++通常经历相同的C/C++编译器和链接器,所以对于C来说它可能同样地工作。

那么...如何回答你的问题?当你觉得足够时使用inline。请注意0​​的可能缺陷。否则,请放弃它,并相信编译器做对了。

+0

不确定此答案的有效性。 “当你觉得它足够时使用内联”表明你可能不会使用它,在链接时你不会得到多个定义错误吗? – 2012-02-25 11:27:59

+0

@Matt乔伊纳:可能,这取决于。我所说的是,对于做'内联'的东西,并没有真正的“正确”或“错误”,就像是否将定义放在标题或源中一样,没有正确也没有错。 - 你可以做这些或两者中的一个,而且没有一个是完全错误的,这是设计选择。无论你是否遇到双重定义(你总是对你的担忧是正确的!)是另一回事。当然有ODR。但是头文件可能只包含一次(我们不知道),并且有'#ifdef',如果没有其他的,如果... – Damon 2012-02-25 18:56:25

+0

...如果OP真的想把一个定义放入一个头文件,但不希望它内联(然后,有编译器功能(如果不需要可移植性),例如'gnu_inline',它又会完全改变规则)。虽然这可能需要在#else子句中另外声明一个extern ...不太好,但是啊...最后,需要选择一个感觉正确的东西。 – Damon 2012-02-25 18:57:48

相关问题