lit*_*adv 98
inline
指示编译器尝试将函数内容嵌入到调用代码中,而不是执行实际调用.
对于频繁调用的小功能,可以产生很大的性能差异.
但是,这只是一个"提示",并且编译器可能会忽略它,并且大多数编译器将尝试"内联",即使在未使用关键字时,作为优化的一部分,也可能.
例如:
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*/};
Run Code Online (Sandbox Code Playgroud)
这个紧密循环将在每次迭代时执行函数调用,并且函数内容实际上明显小于编译器执行调用所需的代码.inline
本质上将指示编译器将上面的代码转换为等效的:
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
Run Code Online (Sandbox Code Playgroud)
跳过实际的函数调用并返回
显然,这是一个显示要点的示例,而不是真正的代码.
static
是指范围.在C中,它表示函数/变量只能在同一个翻译单元中使用.
Chr*_*oph 80
默认情况下,内联定义仅在当前翻译单元中有效.
如果存储类是extern
,则标识符具有外部链接,并且内联定义还提供外部定义.
如果存储类是static
,则标识符具有内部链接,并且内联定义在其他翻译单元中是不可见的.
如果未指定存储类,则内联定义仅在当前转换单元中可见,但标识符仍具有外部链接,并且必须在不同的转换单元中提供外部定义.如果在当前转换单元中调用该函数,则编译器可以自由使用内联或外部定义.
由于编译器可以自由地内联(并且不内联)任何其定义在当前翻译单元中可见的函数(并且,由于链接时优化,即使在不同的翻译单元中,尽管C标准并不真正考虑到那么,对于大多数实际来说,static
和static inline
函数定义之间没有区别.
的inline
说明符(如register
存储类)只有一个编译器暗示,编译器可以自由地完全忽略它.符合标准的非优化编译器只需要遵守它们的副作用,优化编译器将在有或没有明确提示的情况下进行这些优化.
inline
register
但是,并没有用,因为当程序员编写会使优化成为不可能的代码时,他们会指示编译器抛出错误:外部inline
定义不能引用具有内部链接的标识符(因为这些将在不同的翻译单元中不可用)或定义具有静态存储持续时间的可修改局部变量(因为这些变量不会共享翻译单元的状态),并且您不能获取 - register
限定变量的地址.
就个人而言,我用的是约定来标记static
头部也中函数定义inline
,为把函数定义在头文件的主要理由是让他们可以内联.
通常,除了头文件中的声明之外,我只使用static inline
函数和static const
对象定义extern
.
我从来没有写过inline
与存储类不同的函数static
.
ony*_*ony 18
根据我对GCC的经验,我知道static
并且static inline
编译器发出有关未使用函数的警告的方式不同.更确切地说,当您声明static
函数并且它未在当前转换单元中使用时,编译器会生成有关未使用函数的警告,但您可以通过将其更改为禁止该警告static inline
.
因此,我倾向于认为static
应该在翻译单元中使用,并从额外的检查编译器中获益,以找到未使用的函数.并且static inline
应该在头文件中使用以提供可以内联的功能(由于没有外部链接)而不发出警告.
不幸的是,我找不到任何有关该逻辑的证据.即使从GCC文档中我也无法得出结论,inline
禁止使用未使用的功能警告.我很感激,如果有人会分享这个描述的链接.
在C语言中,static
意味着您定义的函数或变量只能在该文件(即编译单元)中使用
因此,static inline
意味着只能在此文件中使用的内联函数。
编辑:
编译单元应该是翻译单元
一个区别不在于语言级别而是流行的实现级别:某些版本的gcc static inline
默认会从输出中删除未引用的函数,但static
即使未引用也会保留普通函数.我不知道这适用于哪个版本,但是从实际情况来看这意味着它可能是一个好主意,始终使用inline
的static
标头的功能.