“静态”和“静态内联”function有什么区别?
国际海事组织(IMO)只是将function做为翻译单位的范围,
“静态”和“静态内联”function有什么区别?
UPDATE
为什么要inline
放在头文件,而不是.c
文件?
inline
指示编译器尝试将函数内容embedded到调用代码中,而不是执行实际调用。
对于经常被调用的小函数,可能会造成巨大的性能差异。
然而,这只是一个“提示”,编译器可能会忽略它,大多数编译器会尝试“内联”,即使在关键字未被使用的情况下,作为优化的一部分,在可能的情况下也是如此。
例如:
static int Inc(int i) {return i+1}; .... // some code int i; .... // some more code for (i=0; i<999999; i = Inc(i)) {/*do something here*/};
这个紧密的循环将在每次迭代中执行函数调用,而函数内容实际上比编译器执行调用所需的代码要less得多。 inline
将主要指示编译器将上面的代码转换为等同于:
int i; .... for (i=0; i<999999; i = i+1) { /* do something here */};
跳过实际的函数调用并返回
显然这是一个例子来显示这一点,而不是一个真正的代码。
static
是指范围。 在C中,这意味着函数/variables只能在同一个翻译单元中使用。
默认情况下,内联定义仅在当前的翻译单元中有效。
如果存储类是extern
,则标识符具有外部链接,并且内联定义也提供外部定义。
如果存储类是static
,则标识符具有内部链接,并且内联定义在其他翻译单元中是不可见的。
如果未指定存储类别,则内联定义仅在当前的翻译单元中可见,但标识符仍具有外部链接,必须在不同的翻译单元中提供外部定义。 如果函数在当前的翻译单元中被调用,编译器可以自由使用内联或外部定义。
由于编译器可以内联(而不内联)任何定义在当前翻译单元中可见的函数(并且,由于链接时优化,甚至在不同的翻译单元中,尽pipeC标准没有真正考虑),大多数实际的目的, static
和static inline
函数定义没有区别。
inline
说明符(如register
存储类)只是一个编译器提示,编译器可以完全忽略它。 符合标准的非优化编译器只需要遵守它们的副作用,优化编译器就可以在有或没有明确提示的情况下进行这些优化。
inline
和register
并不是无用的,因为它们指示编译器在程序员编写代码时会抛出错误,使优化变得不可能:外部inline
定义不能引用具有内部链接的标识符(因为这些标识符在不同的翻译单元),或者定义具有静态存储持续时间的可修改局部variables(因为它们不会共享翻译单元的状态),并且不能获取register
限定variables的地址。
就我个人而言,我使用约定来标记头中的static
函数定义也是inline
,因为在头文件中放置函数定义的主要原因是为了让它们可以被映射。
一般来说,除了标题中的extern
声明之外,我只使用static inline
函数和static const
对象定义。
我从来没有写过一个不同于static
的存储类的inline
函数。
根据我对GCC的经验,我知道static
和static inline
不同之处在于编译器如何发出关于未使用函数的警告。 更确切地说,当你声明static
函数并且它不被当前的翻译单元使用时,编译器会产生关于未使用的函数的警告,但是你可以通过将它改变为static inline
来禁止该警告。
因此,我倾向于认为, static
应该用在翻译单位,并从额外的检查编译器中获益,find未使用的function。 在头文件中应该使用static inline
,以提供可以static inline
function(由于没有外部链接)而不发出警告。
不幸的是,我找不到这个逻辑的证据。 即使从GCC文档,我也无法得出结论, inline
禁止未使用的function警告。 我会很感激,如果有人会分享链接的描述。
一个不同于语言级别但stream行的实现级别的区别:特定版本的gcc将默认从输出中移除未引用的static inline
函数,但即使未引用也会保留纯static
函数。 我不确定这个版本适用于哪个版本,但从实际的angular度来看,这意味着在标题中始终使用inline
static
函数是一个好主意。
在C中, static
意味着你定义的函数或variables只能在这个文件中使用(即编译单元)
所以, static inline
意味着只能在这个文件中使用的内联函数。
编辑:
编译单位应该是翻译单位