“静态”和“静态内联”功能有什么区别?

时间:2021-06-12 13:25:00

IMO both make the function to have a scope of translate unit only,

国际海事组织(IMO)都只让该函数具有翻译单元的范围,

what's the difference between "static" and "static inline" function?

“静态”和“静态内联”功能有什么区别?

UPDATE

更新

why should inline be put in header file, not .c file?

为什么内联应该放在头文件中,而不是。c文件?

5 个解决方案

#1


77  

inline instructs the compiler to attempt to embed the function content into the calling code instead of executing an actual call.

内联指示编译器尝试将函数内容嵌入到调用代码中,而不是执行实际调用。

For small functions that are called frequently that can make a big performance difference.

对于经常被调用的小函数来说,这会带来很大的性能差异。

However, this is only a "hint", and the compiler may ignore it, and most compilers will try to "inline" even when the keyword is not used, as part of the optimizations, where its possible.

然而,这只是一个“提示”,编译器可能会忽略它,而且大多数编译器会尝试“内联”,即使在没有使用关键字时,作为优化的一部分,它也是可能的。

for example:

例如:

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*/};

This tight loop will perform a function call on each iteration, and the function content is actually significantly less than the code the compiler needs to put to perform the call. inline will essentially instruct the compiler to convert the code above into an equivalent of:

这个紧密的循环将在每次迭代中执行一个函数调用,并且函数内容实际上比编译器要执行调用的代码要少得多。内联将实质上指示编译器将上面的代码转换成等价的:

 int i;
 ....
 for (i=0; i<999999; i = i+1) { /* do something here */};

Skipping the actual function call and return

跳过实际的函数调用和返回。

Obviously this is an example to show the point, not a real piece of code.

很明显,这是一个展示点的例子,而不是真正的代码。

static refers to the scope. In C it means that the function/variable can only be used within the same translation unit.

静态指的是范围。在C中,这意味着函数/变量只能在同一个翻译单元中使用。

#2


57  

By default, an inline definition is only valid in the current translation unit.

默认情况下,内联定义仅在当前翻译单元中有效。

If the storage class is extern, the identifier has external linkage and the inline definition also provides the external definition.

如果存储类是外部的,则标识符具有外部链接,并且内联定义也提供了外部定义。

If the storage class is static, the identifier has internal linkage and the inline definition is invisible in other translation units.

如果存储类是静态的,则标识符具有内部链接,而在其他翻译单元中,内联定义是不可见的。

If the storage class is unspecified, the inline definition is only visible in the current translation unit, but the identifier still has external linkage and an external definition must be provided in a different translation unit. The compiler is free to use either the inline or the external definition if the function is called within the current translation unit.

如果存储类未指定,则内联定义仅在当前的翻译单元中可见,但标识符仍然具有外部链接,必须在不同的翻译单元中提供外部定义。如果函数在当前翻译单元内调用,编译器可以*使用内联或外部定义。

As the compiler is free to inline (and to not inline) any function whose definition is visible in the current translation unit (and, thanks to link-time optimizations, even in different translation units, though the C standard doesn't really account for that), for most practical purposes, there's no difference between static and static inline function definitions.

作为内联的编译器是免费的(和不内联)任何函数的定义是可见的在当前的翻译单元(由于链接时优化,即使在不同的翻译单元,尽管C标准并不占),用于最实际的用途,没有区别静态和静态内联函数的定义。

The inline specifier (like the register storage class) is only a compiler hint, and the compiler is free to completely ignore it. Standards-compliant non-optimizing compilers only have to honor their side-effects, and optimizing compilers will do these optimizations with or without explicit hints.

内联说明符(如寄存器存储类)只是一个编译器提示,编译器可以完全忽略它。符合标准的非优化编译器只需要遵守它们的副作用,而优化编译器就会在没有明确提示的情况下进行这些优化。

inline and register are not useless, though, as they instruct the compiler to throw errors when the programmer writes code that would make the optimizations impossible: An external inline definition can't reference identifiers with internal linkage (as these would be unavailable in a different translation unit) or define modifiable local variables with static storage duration (as these wouldn't share state accross translation units), and you can't take addresses of register-qualified variables.

内联和寄存器不是无用的,因为他们指示编译器把错误当程序员写代码的优化不可能:外部内联定义不能引用标识符与内部联系(因为这些不可用在不同的翻译单元)或定义修改本地变量和静态存储时间(因为这些不会跨越翻译单元共享状态),你不能把register-qualified变量的地址。

Personally, I use the convention to mark static function definitions within headers also inline, as the main reason for putting function definitions in header files is to make them inlinable.

就我个人而言,我使用该惯例在头文件内标记静态函数定义,因为在头文件中放置函数定义的主要原因是使它们是不可行的。

In general, I only use static inline function and static const object definitions in addition to extern declarations within headers.

一般来说,我只使用静态内联函数和静态const对象定义,并且在header中添加外部声明。

I've never written an inline function with a storage class different from static.

我从来没有编写过与静态存储类不同的内联函数。

#3


7  

From my experience with GCC I know that static and static inline differs in a way how compiler issue warnings about unused functions. More precisely when you declare static function and it isn't used in current translation unit then compiler produce warning about unused function, but you can inhibit that warning with changing it to static inline.

根据我对GCC的经验,我知道静态和静态内联不同于编译器如何发出关于未使用函数的警告。更准确地说,当您声明静态函数时,它不在当前的翻译单元中使用,然后编译器会对未使用的函数发出警告,但是您可以通过将其更改为静态内联来抑制该警告。

Thus I tend to think that static should be used in translation units and benefit from extra check compiler does to find unused functions. And static inline should be used in header files to provide functions that can be in-lined (due to absence of external linkage) without issuing warnings.

因此,我倾向于认为静态应该在翻译单元中使用,并且从额外的检查编译器中得到的好处是找到未使用的函数。而且,在头文件中应该使用静态内联,以提供在没有发出警告的情况下可以内联的函数(由于没有外部链接)。

Unfortunately I cannot find any evidence for that logic. Even from GCC documentation I wasn't able to conclude that inline inhibits unused function warnings. I'd appreciate if someone will share links to description of that.

不幸的是,我找不到任何关于这种逻辑的证据。即使从GCC的文档中我也不能得出内联抑制未使用的函数警告的结论。如果有人愿意分享这方面的链接,我会很感激。

#4


4  

One difference that's not at the language level but the popular implementation level: certain versions of gcc will remove unreferenced static inline functions from output by default, but will keep plain static functions even if unreferenced. I'm not sure which versions this applies to, but from a practical standpoint it means it may be a good idea to always use inline for static functions in headers.

一个不同的地方不是语言级别,而是流行的实现级别:某些版本的gcc将默认从输出中删除未引用的静态内联函数,但是即使没有引用,也会保持简单的静态函数。我不确定这适用于哪个版本,但是从实际的角度来看,它意味着在头文件中始终使用内联的静态函数可能是个好主意。

#5


2  

In C, static means the function or variable you define can be only used in this file(i.e. the compile unit)

在C中,静态意味着您定义的函数或变量只能在该文件中使用(即:编译单元)

So, static inline means the inline function which can be used in this file only.

因此,静态内联表示只能在此文件中使用的内联函数。

EDIT:

编辑:

The compile unit should be The Translation Unit

编译单元应该是翻译单元。

#1


77  

inline instructs the compiler to attempt to embed the function content into the calling code instead of executing an actual call.

内联指示编译器尝试将函数内容嵌入到调用代码中,而不是执行实际调用。

For small functions that are called frequently that can make a big performance difference.

对于经常被调用的小函数来说,这会带来很大的性能差异。

However, this is only a "hint", and the compiler may ignore it, and most compilers will try to "inline" even when the keyword is not used, as part of the optimizations, where its possible.

然而,这只是一个“提示”,编译器可能会忽略它,而且大多数编译器会尝试“内联”,即使在没有使用关键字时,作为优化的一部分,它也是可能的。

for example:

例如:

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*/};

This tight loop will perform a function call on each iteration, and the function content is actually significantly less than the code the compiler needs to put to perform the call. inline will essentially instruct the compiler to convert the code above into an equivalent of:

这个紧密的循环将在每次迭代中执行一个函数调用,并且函数内容实际上比编译器要执行调用的代码要少得多。内联将实质上指示编译器将上面的代码转换成等价的:

 int i;
 ....
 for (i=0; i<999999; i = i+1) { /* do something here */};

Skipping the actual function call and return

跳过实际的函数调用和返回。

Obviously this is an example to show the point, not a real piece of code.

很明显,这是一个展示点的例子,而不是真正的代码。

static refers to the scope. In C it means that the function/variable can only be used within the same translation unit.

静态指的是范围。在C中,这意味着函数/变量只能在同一个翻译单元中使用。

#2


57  

By default, an inline definition is only valid in the current translation unit.

默认情况下,内联定义仅在当前翻译单元中有效。

If the storage class is extern, the identifier has external linkage and the inline definition also provides the external definition.

如果存储类是外部的,则标识符具有外部链接,并且内联定义也提供了外部定义。

If the storage class is static, the identifier has internal linkage and the inline definition is invisible in other translation units.

如果存储类是静态的,则标识符具有内部链接,而在其他翻译单元中,内联定义是不可见的。

If the storage class is unspecified, the inline definition is only visible in the current translation unit, but the identifier still has external linkage and an external definition must be provided in a different translation unit. The compiler is free to use either the inline or the external definition if the function is called within the current translation unit.

如果存储类未指定,则内联定义仅在当前的翻译单元中可见,但标识符仍然具有外部链接,必须在不同的翻译单元中提供外部定义。如果函数在当前翻译单元内调用,编译器可以*使用内联或外部定义。

As the compiler is free to inline (and to not inline) any function whose definition is visible in the current translation unit (and, thanks to link-time optimizations, even in different translation units, though the C standard doesn't really account for that), for most practical purposes, there's no difference between static and static inline function definitions.

作为内联的编译器是免费的(和不内联)任何函数的定义是可见的在当前的翻译单元(由于链接时优化,即使在不同的翻译单元,尽管C标准并不占),用于最实际的用途,没有区别静态和静态内联函数的定义。

The inline specifier (like the register storage class) is only a compiler hint, and the compiler is free to completely ignore it. Standards-compliant non-optimizing compilers only have to honor their side-effects, and optimizing compilers will do these optimizations with or without explicit hints.

内联说明符(如寄存器存储类)只是一个编译器提示,编译器可以完全忽略它。符合标准的非优化编译器只需要遵守它们的副作用,而优化编译器就会在没有明确提示的情况下进行这些优化。

inline and register are not useless, though, as they instruct the compiler to throw errors when the programmer writes code that would make the optimizations impossible: An external inline definition can't reference identifiers with internal linkage (as these would be unavailable in a different translation unit) or define modifiable local variables with static storage duration (as these wouldn't share state accross translation units), and you can't take addresses of register-qualified variables.

内联和寄存器不是无用的,因为他们指示编译器把错误当程序员写代码的优化不可能:外部内联定义不能引用标识符与内部联系(因为这些不可用在不同的翻译单元)或定义修改本地变量和静态存储时间(因为这些不会跨越翻译单元共享状态),你不能把register-qualified变量的地址。

Personally, I use the convention to mark static function definitions within headers also inline, as the main reason for putting function definitions in header files is to make them inlinable.

就我个人而言,我使用该惯例在头文件内标记静态函数定义,因为在头文件中放置函数定义的主要原因是使它们是不可行的。

In general, I only use static inline function and static const object definitions in addition to extern declarations within headers.

一般来说,我只使用静态内联函数和静态const对象定义,并且在header中添加外部声明。

I've never written an inline function with a storage class different from static.

我从来没有编写过与静态存储类不同的内联函数。

#3


7  

From my experience with GCC I know that static and static inline differs in a way how compiler issue warnings about unused functions. More precisely when you declare static function and it isn't used in current translation unit then compiler produce warning about unused function, but you can inhibit that warning with changing it to static inline.

根据我对GCC的经验,我知道静态和静态内联不同于编译器如何发出关于未使用函数的警告。更准确地说,当您声明静态函数时,它不在当前的翻译单元中使用,然后编译器会对未使用的函数发出警告,但是您可以通过将其更改为静态内联来抑制该警告。

Thus I tend to think that static should be used in translation units and benefit from extra check compiler does to find unused functions. And static inline should be used in header files to provide functions that can be in-lined (due to absence of external linkage) without issuing warnings.

因此,我倾向于认为静态应该在翻译单元中使用,并且从额外的检查编译器中得到的好处是找到未使用的函数。而且,在头文件中应该使用静态内联,以提供在没有发出警告的情况下可以内联的函数(由于没有外部链接)。

Unfortunately I cannot find any evidence for that logic. Even from GCC documentation I wasn't able to conclude that inline inhibits unused function warnings. I'd appreciate if someone will share links to description of that.

不幸的是,我找不到任何关于这种逻辑的证据。即使从GCC的文档中我也不能得出内联抑制未使用的函数警告的结论。如果有人愿意分享这方面的链接,我会很感激。

#4


4  

One difference that's not at the language level but the popular implementation level: certain versions of gcc will remove unreferenced static inline functions from output by default, but will keep plain static functions even if unreferenced. I'm not sure which versions this applies to, but from a practical standpoint it means it may be a good idea to always use inline for static functions in headers.

一个不同的地方不是语言级别,而是流行的实现级别:某些版本的gcc将默认从输出中删除未引用的静态内联函数,但是即使没有引用,也会保持简单的静态函数。我不确定这适用于哪个版本,但是从实际的角度来看,它意味着在头文件中始终使用内联的静态函数可能是个好主意。

#5


2  

In C, static means the function or variable you define can be only used in this file(i.e. the compile unit)

在C中,静态意味着您定义的函数或变量只能在该文件中使用(即:编译单元)

So, static inline means the inline function which can be used in this file only.

因此,静态内联表示只能在此文件中使用的内联函数。

EDIT:

编辑:

The compile unit should be The Translation Unit

编译单元应该是翻译单元。