【问题标题】:small functions defined in header files: inline or static?头文件中定义的小函数:内联还是静态?
【发布时间】:2012-03-14 18:23:36
【问题描述】:

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

我知道在标题中定义函数通常是不好的做法。您不必在答案中提及,这个问题是技术上的。

【问题讨论】:

  • 在标题中实现它们是不好的,而不是定义它们;)
  • C/C++ 中的头文件的想法为开发人员创造了额外的工作,我知道没有人想复制声明
  • 代码量小或功能小:D?
  • @m0skit0:我知道的 C 术语是 declarationdefinition
  • @m0skit0,定义和实现是一回事!剩下的就是申报了。 :)

标签: c static inline header-files


【解决方案1】:

我认为 static inline 是您想要内联的功能的方式,而只有 static 适合您不想要的功能。

static 指的是可见性,但 inline 在标准 (C99) 中对可见性的含义是模棱两可的。无论如何,这不是它的目的:inline 用于内联函数,因此从可见性的角度来看,它具有您可能不想要的副作用。

【讨论】:

  • 你忽略了解释原因。
  • "inline 不明确,也允许使用 extern 关键字,这违背了您的目的。"
  • 我扩展了我的解释,希望你在投反对票时发表评论,这样我(我们)可以学习;)
  • 正如其他答案中所讨论的,内联没有您在此答案中推断的含义。
【解决方案2】:

我会使用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)

提供外部定义的替代方案,翻译人员可以使用它来实现 在同一个翻译单元中对函数的任何调用。未指定是否调用 函数使用内联定义或外部定义。

即内联定义应始终伴随着外部定义,这不是您要寻找的。​​p>

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

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

【讨论】:

  • @Heptic:标准的措辞有些模棱两可,但据我了解,编译器总是可以完全忽略任何内联定义并退回到外部定义,如果其他翻译单元中没有这样的定义...
  • @Heptic:我的解释似乎是正确的 - 请参阅随附的示例,即 C99 7.6.4 §8
  • @Heptic:此外,并非所有主要编译器/链接器都按照您描述的方式工作 - 除了 clang,如果存在 -std=c99-std=gnu99,gcc 还尊重 C99 语义......跨度>
  • 触摸。 C99 标准与您一致。我看不出他们的决定背后有任何逻辑,特别是考虑到 gcc/c++/msvc 做得正确,但这是一个单独的问题。
  • static inline 意味着每个翻译单元都有自己的函数副本。这会增加二进制文件的大小。 inline 使所有翻译单元共享一个功能。另见stackoverflow.com/questions/10847176
【解决方案3】:

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

  1. 您希望“尽可能快地调用函数”(ISO9899-1999, 6.7.4(5))。同一段还指出,该建议在何种程度上有效是由实现定义的。换句话说,它几乎没有影响,并且根本不意味着任何内联(事实上,由于指令缓存的影响,非内联可能会更快)。
  2. 结合extern(ISO9899-1999, 6.7.4(6))有一些限制和特殊情况,例如必须在同一编译单元中定义具有外部链接的inline函数,并且inline definition 允许在别处定义extern 而不会出错(这未必是件好事,因为这两个函数不需要在功能上等价,而且编译器在任何时候都未指定使用哪一个! )。

Heptic 给出的链接器含义是 C++ 所必需的,但 C 不是必需的(据我所知)。 ISO14882, 7.1.2(4) 中的“在所有翻译单元中应具有相同的地址” 条款必须要求它们。我不知道 C99 中有任何类似的条款。
但是,由于完全不同的语言 C 和 C++ 通常通过相同的 C/C++ 编译器和链接器,所以无论如何它对于 C 的工作方式可能相同。

那么...如何回答您的问题?当您觉得足够时使用inline。请注意extern 可能存在的陷阱。否则,别管它,相信编译器会做对。

【讨论】:

  • 不确定这个答案的有效性。 “当你觉得足够时使用内联”表明你可能不会使用它,你不会在链接时遇到多个定义错误吗?
  • @Matt Joiner:可能,这取决于。我要说的是,对于制作 inline 而言,没有真正的“正确”或“错误”,就像在标题或源中放置定义没有对错一样——你可以做其中之一或两者都做,一般都没有错,这是一种设计选择。您是否遇到双重定义的麻烦(您的担忧通常是正确的!)是另一回事。肯定有 ODR。但是标题可能只包含一次(我们不知道),并且有#ifdef,如果没有别的,以防万一......
  • ... 如果 OP 真的想将定义放入标头中,但不希望将其内联(然后,有编译器功能(如果不严格要求可移植性),例如gnu_inline 再次完全改变规则。)。虽然这可能需要在 #else 子句中再声明一个 extern ......不是很漂亮,但是嗯......最后,人们需要选择感觉正确的一件事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 2013-12-31
  • 1970-01-01
  • 2021-11-29
  • 1970-01-01
相关资源
最近更新 更多