我有一些在.h
文件中定义的小函数。这是一个小型项目(现在),我想避免声明和定义分开的痛苦,因为它们一直都在变化。为了避免多重定义的符号,我可以让他们static
或inline
。什么应该是首选,为什么?在头文件中定义的小函数:内联还是静态?
我知道在头文件中定义函数通常是不好的做法。你不必在答案中提到,这个问题在技术上意味着。
我有一些在.h
文件中定义的小函数。这是一个小型项目(现在),我想避免声明和定义分开的痛苦,因为它们一直都在变化。为了避免多重定义的符号,我可以让他们static
或inline
。什么应该是首选,为什么?在头文件中定义的小函数:内联还是静态?
我知道在头文件中定义函数通常是不好的做法。你不必在答案中提到,这个问题在技术上意味着。
我会用static inline
,但static
也可以。
extern
和extern inline
都出来了,因为如果头被包含在一个以上的翻译单元,你会得到多个外部定义,所以你需要考虑static
,static inline
和inline
规范。
Heptic在他的答案正确地指出,大多数编译器考虑功能无论是否指定inline
的或不内联,即inline
的主要影响是其对联动效应。
但是,static
定义有内部联系,所以static
和static inline
之间没有太大的区别;我更喜欢static inline
在纯粹的文体原因的头文件中的函数定义(经验法则:头文件应该只包含extern
声明,static const
变量定义和static inline
函数定义)。
inline
而不static
或extern
导致一个直列定义,其标准状态(C99 6.7.4,§6)
提供到外部的定义,其中转换器可用于替代执行 对同一个翻译单元中的函数的任何调用。不确定对 函数的调用是使用内联定义还是外部定义。
即内联定义应该总是伴随着外部定义,这不是你正在寻找的。
有关C99内联语义的细微之处的更多信息,请参见this answer,Clang homepage和C99 Rationale (PDF)。
请记住,如果有-std=c99
或-std=gnu99
存在,GCC将只使用C99语义...
@Heptic:标准的措辞有点含糊不清,但据我了解,编译器总是可以自由地完全忽略任何内联定义并回退到外部定义,如果没有这样的定义,这显然会失败在另一个翻译单位中...... – Christoph 2012-02-24 12:19:02
@Heptic:我的解释似乎是正确的 - 请参阅随附的示例,即C99 7.6.4§8 – Christoph 2012-02-24 12:21:51
@Heptic:另外,并非所有主要编译器/链接程序都以您描述的方式工作 - 此外如果'-std = c99'或'-std = gnu99'存在,gcc也尊重C99的语义...... – Christoph 2012-02-24 12:48:58
由于问题是关于C(不是C++),inline
意味着
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的可能缺陷。否则,请放弃它,并相信编译器做对了。
不确定此答案的有效性。 “当你觉得它足够时使用内联”表明你可能不会使用它,在链接时你不会得到多个定义错误吗? – 2012-02-25 11:27:59
@Matt乔伊纳:可能,这取决于。我所说的是,对于做'内联'的东西,并没有真正的“正确”或“错误”,就像是否将定义放在标题或源中一样,没有正确也没有错。 - 你可以做这些或两者中的一个,而且没有一个是完全错误的,这是设计选择。无论你是否遇到双重定义(你总是对你的担忧是正确的!)是另一回事。当然有ODR。但是头文件可能只包含一次(我们不知道),并且有'#ifdef',如果没有其他的,如果... – Damon 2012-02-25 18:56:25
...如果OP真的想把一个定义放入一个头文件,但不希望它内联(然后,有编译器功能(如果不需要可移植性),例如'gnu_inline',它又会完全改变规则)。虽然这可能需要在#else子句中另外声明一个extern ...不太好,但是啊...最后,需要选择一个感觉正确的东西。 – Damon 2012-02-25 18:57:48
**在**头文件中实现它们是不好的,而不是定义它们;) – m0skit0 2012-02-24 09:40:39
C/C++中头文件的思想为开发人员创造了额外的工作,我知道没有人想要复制代码大小小的声明 – linquize 2012-02-24 09:42:44
或者它的功能很小:D? – UmNyobe 2012-02-24 09:43:31