C语言 C中`inline`关键字的用途是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31108159/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 12:01:38  来源:igfitidea点击:

What is the use of the `inline` keyword in C?

cinlinec99

提问by xiver77

I read several questions in stackoverflow about inlinein C but still am not clear about it.

我在stackoverflow中阅读了几个关于inlineC的问题,但仍然不清楚。

  1. static inline void f(void) {}has no practical difference with static void f(void) {}.
  2. inline void f(void) {}in C doesn't work as the C++ way. How does it work in C?
  3. What actually does extern inline void f(void);do?
  1. static inline void f(void) {}与 没有实际区别static void f(void) {}
  2. inline void f(void) {}在 C 中不能像 C++ 方式那样工作。它在 C 中是如何工作的?
  3. 实际上有extern inline void f(void);什么作用?

I never really found a use of the inlinekeyword in my C programs, and when I see this keyword in other people's code, it's almost always static inline, in which I see no difference with just static.

我从来没有真正inline在我的 C 程序中找到过关键字的用法,当我在其他人的代码中看到这个关键字时,几乎总是这样static inline,我发现它与static.

采纳答案by M.M

Note: when I talk about .cfiles and .hfiles in this answer, I assume you have laid out your code correctly, i.e. .cfiles only include .hfiles. The distinction is that a .hfile may be included in multiple translation units.

注意:当我在这个答案中谈论.c文件和.h文件时,我假设你已经正确地布置了你的代码,即.c文件只包含.h文件。区别在于一个.h文件可能包含在多个翻译单元中。

static inline void f(void) {}has no practical difference with static void f(void) {}.

static inline void f(void) {}与 没有实际区别static void f(void) {}

In ISO C, this is correct. They are identical in behaviour (assuming you don't re-declare them differently in the same TU of course!) the only practical effect may be to cause the compiler to optimize differently.

在 ISO C 中,这是正确的。它们的行为是相同的(当然,假设您没有在同一个 TU 中以不同的方式重新声明它们!)唯一的实际效果可能是导致编译器以不同的方式优化。

inline void f(void) {}in C doesn't work as the C++ way. How does it work in C? What actually does extern inline void f(void);do?

inline void f(void) {}在 C 中不能像 C++ 方式那样工作。它在 C 中是如何工作的?实际上有extern inline void f(void);什么作用?

This is explained by this answerand also this thread.

这由this answerthis thread解释

In ISO C and C++, you can freely use inline void f(void) {}in header files -- although for different reasons!

在 ISO C 和 C++ 中,您可以inline void f(void) {}在头文件中自由使用——尽管原因不同!

In ISO C, it does not provide an external definition at all. In ISO C++ it does provide an external definition; however C++ has an additional rule (which C doesn't), that if there are multiple external definitions of an inlinefunction, then the compiler sorts it out and picks one of them.

在 ISO C 中,它根本不提供外部定义。在 ISO C++ 中,它确实提供了一个外部定义;然而 C++ 有一个额外的规则(C 没有),如果一个inline函数有多个外部定义,那么编译器会对其进行分类并选择其中一个。

extern inline void f(void);in a .cfile in ISO C is meant to be paired with the use of inline void f(void) {}in header files. It causes the external definitionof the function to be emitted in that translation unit. If you don't do this then there is no external definition, and so you may get a link error (it is unspecified whether any particular call of flinks to the external definition or not).

extern inline void f(void);.cISO C中的文件中意在与inline void f(void) {}in 头文件中的使用配对。它导致在该翻译单元中发出函数的外部定义。如果您不这样做,则没有外部定义,因此您可能会收到链接错误(未指定是否有任何特定f的外部定义链接调用)。

In other words, in ISO C you can manually select where the external definition goes; or suppress external definition entirely by using static inlineeverywhere; but in ISO C++ the compiler chooses if and where an external definition would go.

换句话说,在 ISO C 中,您可以手动选择外部定义的位置;或通过static inline在任何地方使用来完全抑制外部定义;但在 ISO C++ 中,编译器选择外部定义是否以及在哪里。

In GNU C, things are different (more on this below).

在 GNU C 中,情况有所不同(更多内容见下文)。

To complicate things further, GNU C++ allows you to write static inlinean extern inlinein C++ code... I wouldn't like to guess on what that does exactly

为了使事情变得复杂进一步,GNU C ++允许你写static inline一个extern inline在C ++代码...我不喜欢猜,做究竟是什么

I never really found a use of the inline keyword in my C programs, and when I see this keyword in other people's code, it's almost always static inline

我从来没有真正在我的 C 程序中找到 inline 关键字的使用,当我在其他人的代码中看到这个关键字时,它几乎总是静态内联

Many coders don't know what they're doing and just put together something that appears to work. Another factor here is that the code you're looking at might have been written for GNU C, not ISO C.

许多程序员不知道他们在做什么,只是把一些看起来有效的东西放在一起。这里的另一个因素是您正在查看的代码可能是为 GNU C 而不是 ISO C 编写的。

In GNU C, plain inlinebehaves differently to ISO C. It actually emits an externally visible definition, so having a .hfile with a plain inlinefunction included from two translation units causes undefined behaviour.

GNU C 中,plain 的inline行为与 ISO C 不同。它实际上发出一个外部可见的定义,因此具有一个包含来自两个翻译单元.h的普通inline函数的文件会导致未定义的行为。

So if the coder wants to supply the inlineoptimization hint in GNU C, then static inlineis required. Since static inlineworks in both ISO C and GNU C, it's natural that people ended up settling for that and seeing that it appeared to work without giving errors.

因此,如果编码人员想inline在 GNU C 中提供优化提示,则static inline需要。由于static inline在 ISO C 和 GNU C 中都可以使用,很自然地,人们最终会接受并看到它似乎可以正常工作而不会出错。

, in which I see no difference with just static.

,其中我认为与静态没有区别。

The difference is just in the intent to provide a speed-over-size optimization hint to the compiler. With modern compilers this is superfluous.

区别仅在于向编译器提供超大速度优化提示的意图。对于现代编译器,这是多余的。

回答by WedaPashi

A C code can be optimized in two ways: For Code size and for Execution Time.

AC 代码可以通过两种方式进行优化:代码大小和执行时间。

inline functions:

内联函数:

gcc.gnu.orgsays,

gcc.gnu.org说,

By declaring a function inline, you can direct GCC to make calls to that function faster. One way GCC can achieve this is to integrate that function's code into the code for its callers. This makes execution faster by eliminating the function-call overhead; in addition, if any of the actual argument values are constant, their known values may permit simplifications at compile time so that not all of the inline function's code needs to be included. The effect on code size is less predictable; object code may be larger or smaller with function inlining, depending on the particular case.

通过声明一个内联函数,您可以指示 GCC 更快地调用该函数。GCC 实现此目的的一种方法是将该函数的代码集成到其调用者的代码中。这通过消除函数调用开销使执行速度更快;此外,如果任何实际参数值是常量,它们的已知值可能允许在编译时进行简化,因此不需要包含所有内联函数的代码。对代码大小的影响较难预测;对象代码可能更大或更小,函数内联取决于特定情况。

So, it tells the compiler to build the function into the code where it is used with the intention of improving execution time.

因此,它告诉编译器将函数构建到使用它的代码中,目的是提高执行时间。

If you declare Small functions like setting/clearing a flag or some bit toggle which are performed repeatedly, inline, it can make a big performance difference with respect to time, but at the cost of code size.

如果您声明诸如设置/清除标志或一些重复执行的位切换之类的小函数inline,它可以在时间方面产生很大的性能差异,但以代码大小为代价。



non-static inline and Static inline

非静态内联和静态内联

Again referring to gcc.gnu.org,

再次参考gcc.gnu.org

When an inline function is not static, then the compiler must assume that there may be calls from other source files; since a global symbol can be defined only once in any program, the function must not be defined in the other source files, so the calls therein cannot be integrated. Therefore, a non-static inline function is always compiled on its own in the usual fashion.

当内联函数不是静态的时,编译器必须假设可能有来自其他源文件的调用;由于全局符号在任何程序中只能定义一次,因此该函数不得在其他源文件中定义,因此无法集成其中的调用。因此,非静态内联函数总是以通常的方式自行编译。



extern inline?

外部内联?

Again, gcc.gnu.org, says it all:

同样,gcc.gnu.org说明了一切:

If you specify both inline and extern in the function definition, then the definition is used only for inlining. In no case is the function compiled on its own, not even if you refer to its address explicitly. Such an address becomes an external reference, as if you had only declared the function, and had not defined it.

如果在函数定义中同时指定 inline 和 extern,则该定义仅用于内联。在任何情况下,函数都不会自行编译,即使您明确引用其地址也不会。这样的地址变成了外部引用,就好像您只声明了函数而没有定义它一样。

This combination of inline and extern has almost the effect of a macro. The way to use it is to put a function definition in a header file with these keywords, and put another copy of the definition (lacking inline and extern) in a library file. The definition in the header file causes most calls to the function to be inlined. If any uses of the function remain, they refer to the single copy in the library.

这种 inline 和 extern 的组合几乎具有宏的效果。使用它的方法是将一个函数定义放在带有这些关键字的头文件中,并将定义的另一个副本(缺少 inline 和 extern)放在一个库文件中。头文件中的定义导致对函数的大多数调用被内联。如果该函数的任何用途仍然存在,它们将引用库中的单个副本。



To sum it up:

把它们加起来:

  1. For inline void f(void){}, inlinedefinition is only valid in the current translation unit.
  2. For static inline void f(void) {}Since the storage class is static, the identifier has internal linkage and the inlinedefinition is invisible in other translation units.
  3. For extern inline void f(void);Since the storage class is extern, the identifier has external linkage and the inline definition also provides the external definition.
  1. 对于inline void f(void){}inline定义仅在当前翻译单元中有效。
  2. 对于static inline void f(void) {}由于存储类是static,所述标识符具有内部联动和inline定义在其他翻译单元不可见的。
  3. 对于extern inline void f(void);由于存储类是extern,所述标识符具有外部键和内联定义还提供了外部定义。

回答by Mohit Jain

From 6.7.4 Function specifiersin C11 specs

来自C11 规范中的6.7.4 函数说明符

6 A function declared with an inline function specifier is an inline function. Making a function an inline function suggests that calls to the function be as fast as possible.138)The extent to which such suggestions are effective is implementation-defined.139)

138) By using, for example, an alternative to the usual function call mechanism, such as inline substitution. Inline substitution is not textual substitution, nor does it create a new function. Therefore, for example, the expansion of a macro used within the body of the function uses the definition it had at the point the function body appears, and not where the function is called; and identifiers refer to the declarations in scope where the body occurs. Likewise, the function has a single address, regardless of the number of inline definitions that occur in addition to the external definition.

139) For example, an implementation might never perform inline substitution, or might only perform inline substitutions to calls in the scope of an inline declaration.

6 用内联函数说明符声明的函数是内联函数。使函数成为内联函数意味着对该函数的调用尽可能快。138)这些建议的有效程度是由 实施定义的139)

138) 例如,通过使用常用函数调用机制的替代方法,例如内联替换。内联替换不是文本替换,也不会创建新函数。因此,例如,在函数体内使用的宏的扩展使用它在函数体出现时的定义,而不是在调用函数的地方;和标识符是指主体出现的范围内的声明。同样,该函数具有单个地址,而不管在外部定义之外出现的内联定义的数量如何。

139) 例如,一个实现可能 永远不会执行内联替换,或者可能只对内联声明范围内的调用执行内联替换。

It suggests compiler that this function is widely used and requests to prefer speed in invocation of this function. But with modern intelligent compiler this may be more or less irrelevant as compilers can decide whether a function should be inlined and may ignore the inline request from users, because modern compilers can very effectively decide about how to invoke the functions.

它建议编译器广泛使用该函数,并要求优先考虑调用该函数的速度。但是对于现代智能编译器,这可能或多或少无关,因为编译器可以决定是否应该内联函数,并且可能会忽略用户的内联请求,因为现代编译器可以非常有效地决定如何调用函数。

static inline void f(void) {}has no practical difference with static void f(void) {}.

static inline void f(void) {}与 没有实际区别static void f(void) {}

So yes with modern compilers most of the time none. With any compilers there are nopractical / observable output differences.

所以大多数时候现代编译器都没有。任何编译器都没有实际/可观察的输出差异。

inline void f(void) {}in C doesn't work as the C++ way. How does it work in C?

inline void f(void) {}在 C 中不能像 C++ 方式那样工作。它在 C 中是如何工作的?

A function that is inline anywhere must be inline everywhere in C++ and linker does not complain multiple definition error (definition must be same).

在任何地方内联的函数在 C++ 中必须在任何地方内联,并且链接器不会抱怨多个定义错误(定义必须相同)。

What actually does extern inline void f(void); do?

extern inline void f(void); 实际上是什么?做?

This will provide external linkage to f. Because the fmay be present in other compilation unit, a compiler may choose different call mechanism to speed up the calls or may ignore the inlinecompletely.

这将为f. 因为f可能存在于其他编译单元中,编译器可能会选择不同的调用机制来加速调用,或者可能会inline完全忽略。

回答by Alekhya Vemavarapu

A function where all the declarations (including the definition) mention inline and never extern.
There must be a definition in the same translation unit. The standard refers to this as an inline definition.
No stand-alone object code is emitted, so this definition can't be called from another translation unit.

一个函数,其中所有声明(包括定义)都提到 inline 而从不 extern。
在同一个翻译单元中必须有一个定义。该标准将此称为内联定义。
不会发出独立的目标代码,因此无法从另一个翻译单元调用此定义。

In this example, all the declarations and definitions use inline but not extern:

在这个例子中,所有的声明和定义都使用 inline 而不是 extern:

// a declaration mentioning inline     
inline int max(int a, int b);

// a definition mentioning inline  
inline int max(int a, int b) {  
  return a > b ? a : b;  
}

Hereis a reference which can give you more clarity on the inline functions in C & also on the usage of inline & extern.

是一个参考,它可以让您更清楚地了解 C 中的内联函数以及内联和外联的用法。

回答by user3805321

As a word "Inline" say "In" "Line", adding this keyword to function affects the program in runtime , when a program is compiled ,the code written insides function is pasted under the function call , as function calls are more costly than inline code, so this optimizes the code. So, static inline void f(void) {} and static void f(void) {} , in this inline keyword do makes difference in runtime. But when function has too many lines of code then it won't effect runtime. If you add static before function , function's life time is the life time of the whole program. And that function use is restricted to that file only. To know about extern you can refer to - Effects of the extern keyword on C functions

就像“Inline”说的“In”“Line”,在函数中添加这个关键字会影响程序在运行时的运行,当一个程序被编译时,写在函数内部的代码被粘贴在函数调用之下,因为函数调用比函数调用成本更高。内联代码,所以这优化了代码。因此, static inline void f(void) {} 和 static void f(void) {} ,在这个内联关键字中确实在运行时有所不同。但是当函数的代码行太多时,它不会影响运行时。如果在 function 之前添加 static ,则 function 的生命周期就是整个程序的生命周期。并且该功能的使用仅限于该文件。要了解 extern,您可以参考 - Extern 关键字对 C 函数的影响