我正在为几个编译器构建一个C项目,其中一些是遗留编译器,似乎没有链接时间内联支持,所以将static inline
函数直接放在头文件中并实际上每个都是合乎逻辑的翻译单位有自己的副本。
另外,我需要确保内联某些函数,以便在某些低级中断处理程序中调用时不会调用其他函数(即更改CPU寄存器),因此它不仅仅是让编译器选择它是否会影响表现。
然而,我的一位同事告诉我这是一件不寻常的事情,我应该避免。在项目的这一点上,我可能仍然可以重新排列所有内容,所以如果我们决定使用标题内联,我只想确认从长远来看是否会遇到一些问题?
答案 0 :(得分:3)
从n1570(最新公开C11草案),§6.7.4:
- 使用
醇>inline
函数说明符声明的函数是内联函数。制作一个 函数内联函数表明对函数的调用尽可能快。这些建议有效的程度是实施定义的。
下一节详细介绍了链接,但上面的这段话基本上都是C标准关于inline
的所有内容。请注意这是如何实现每个自由的,包括完全忽略inline
。
因此,只使用标准C,您可能会以正常方式调用函数的多个实例(每个翻译单元一个)。这通常不是您想要的,因为它结合了两个缺点(重复代码和函数调用的开销)。所以我认为标准C inline
仅对单个翻译单元的私有函数有用。即使这样,你也可以假设一个好的优化编译器会自动选择内联的候选者,而没有明确的inline
。
另一方面,如果您的编译器提供了一种实际强制内联函数的方法(根据您的注释,_inline
说明符为您的编译器执行),具有这些函数在标题中是安全的。但请注意,它绝不是便携式的。
作为commented by cmaster,您可以使用类似函数的宏实现“手动内联”,而不是便携式解决方案。< / p>
答案 1 :(得分:2)
根据对该问题的评论,在头文件中定义static _inline
函数是为此特定编译器的方法,编译器文档中的引用很清楚。< / p>
您可能在以后遇到的问题是它是特定编译器的特定扩展,与标准 inline
说明符不同。正如Felix所说,标准允许实现选择它如何实现内联,特别是忽略说明符仍然符合:
使函数成为内联函数表明对函数的调用为as 尽可能快。 此类建议有效的程度如下 实现定义强>
话虽如此,语义似乎是相同的(从C99的草案1256或C11的草案1570):
6.7.4函数说明符
...
具有内部链接的任何函数都可以是内联函数。用于外部功能 链接,以下限制适用:如果使用内联声明函数 函数说明符,那么它也应该在同一个翻译单元中定义。如果所有的 翻译单元中函数的文件范围声明包括内联函数 没有extern的说明符,那么该翻译单元中的定义是内联的 定义。内联定义不提供函数的外部定义, 并且不禁止在另一个翻译单元中使用外部定义。内联定义 提供了外部定义的替代方案,翻译人员可以使用该定义来实现 在同一翻译单元中对该功能的任何调用。没有具体说明是否打电话给 函数使用内联定义或外部定义
因为普通实现确实尊重inline
说明符,我认为可移植性的风险是有限的
答案 2 :(得分:0)
没有必要将函数声明为static inline
,因为ISO 9899
保证在您不使用存储类说明符{{1}时不会将函数导出到链接器在翻译单元中的内联函数的任何声明中。
换句话说,如果您只是将其声明为extern
,则无法从外部看到符号inline aaa
。
我引自aaa
如果翻译中的函数的所有文件范围声明 单位包括没有extern的内联函数speci,然后是 该翻译单元中的定义是内联定义。一个 内联定义不提供外部定义 功能,并不禁止另一个人的外部定义 翻译单位。
emacs在6.7.4 Function specifiers
中使用这种内联技术,定义了lisp对象的标题,我引用了emacs的源代码:
有些操作通常被执行以便实现 作为宏,而不是函数,因为否则运行时性能会 在没有优化的情况下使用GCC进行编译时会受到太大的影响 没有必要内联所有内容,只需要导致严重性能问题的操作。