This article describes the differences in the use of inline in GCC and C99 standards. Inline property In use, note the following two points: the inline keyword is used only in theGCC reference documentation for its use on function definitions (definition), without mentioning whether it can be used for function declarations (Declare).
From the inline role, it should be placed in the function declaration is also useless: inline will only affect the function in the translation unit (can be simply understood as a C source file) within the compilation behavior, as long as beyond the scope of the inline property does not have any effect. Therefore, the inline keyword should not appear in the function declaration, does not have any effect to say, sometimes may also cause the compilation error (in the case that contains the Sys/compiler.h, the part that appears the inline keyword in the declaration usually cannot compile the pass);
The inline keyword simply suggests that the compiler do inline expansion rather than coercion. In the GCC compiler, if the compilation optimization is set to-o0, even the inline function is not expanded inline unless the forced inline (__attribute__ (always_inline)) attribute is set.
1. GCC's inline
GCC has made its own expansion of the inline of C language, and its behavior differs greatly from the inline in the C99 standard.
The static inline definition for
1.1. Static inline
GCC is easy to understand: you can think of it as a static function, plus a inline attribute. Most of this function behaves like a normal static function, except that when invoking this function, GCC expands its remit code at its call to compile without generating a separate assembler for the function. Except in the following cases: The address of the
(1) function is used. The function is called indirectly through the function pointer. In this case, you have to generate a separate sink code for the static inline function, otherwise it does not have its own address.
(2) Some other situations that cannot be expanded, such as the function itself has recursive invocation of its own behavior. The
static inline function, like the static function, has a defined scope that is local, that is, you can have multiple definitions of the same name within a program (as long as it is not within the same file).
Note : GCC's static inline behaves in a consistent and C99 standard static inline. So this definition is safe to use without compatibility issues.
Important: The static inline of
gcc is only recommended for inline expansion of the compiler when invoked, relative to the static function;
GCC does not deliberately generate a separate sink encoding for the static inline function unless there is a situation that must be generated (for example, by function pointer invocation and recursive invocation);
GCC's static inline function can only be used in file scope.
1.2. Inline
compared to C99 inline, GCC's inline is easier to understand: it can be thought of as a normal global function plus a inline attribute. That is, within the file in which it is defined, its performance is consistent with the static inline: it is compiled inline when it can be expanded. But in order to be able to use it outside of the file, GCC will certainly generate a separate remit code for it to be invoked externally. That is, from the outside of the file, it is the same as an ordinary extern function. For example:
FOO.C: /* This defines a inline function foo () */ Inline foo () { ...; <-compiler will generate a standalone assembler } void Func1 () { foo (), <-same file foo () as a inline function. When you invoke Foo () in another file, which may be compiled inline by the compiler rather than directly call the assembly code } above, the assembly code generated in the above file is called directly: bar.c: extern foo (); <- declare foo (), note that you cannot bring the inline keyword void Func2 () { foo (); in the Declaration <- Here's the direct call. The assembly code generated for the Foo () function in FOO.C } |
Important : Although the behavior of GCC's inline function is well understood, it differs greatly from the inline of C99. Please note the description of the face C99 inline (Section 2.2 "inline") and how to use the inline function in a way that takes into account both GCC and C99.
Important :
(1) GCC's inline function, as opposed to ordinary extern functions, suggests that the compiler do inline expansion only when invoked within the same file;
(2) GCC will certainly generate a separate remit encoding for the inline function so that it is invoked outside of this file. In other files, this inline function is no different from a normal extern function; the inline function of
(3) C is global: it can be expanded inline as an inline function within a file and can be invoked outside of a file. The static inline and inline of
1.3. extern inline
GCC are well understood: it all seems like adding inline properties to normal functions. But this extern inline must not be taken for granted as an extern function +inline attribute. In fact, GCC's extern inline is very bizarre: an extern inline function is only inline, and it never generates a separate assembler code. A call to this function is processed as an external reference, even if the pointer or recursive call does not allow the compiler to generate a sink encoding for it. In addition, the functions of the extern inline allow the same name as the external function, that is, it is also legal to define an extern inline function with the same names in the case of an externally defined global library function. The following examples illustrate the characteristics of the extern inline:
FOO.C: extern inline int foo (int a) { return (a); } void Func1 () { ...; A = foo (a); ① P_foo = foo; Ii b = P_foo (b); ③ } |
In this file, GCC does not generate an assembly code for the Foo function. At the call point in Func1 ①, the compiler expands and compiles the Foo function defined above, which behaves like a normal inline function. Because such calls are capable of inline processing. At ②, the address of the Foo function is referenced. Note, however, that the compiler is absolutely not going to generate a standalone sink for the extern inline function. So in this case, the compiler will have to process it as an external reference and link it to the outside Foo function (fill out the address of the external function) when the function address is not available. at this point, if there is no further definition of the global Foo function, it will produce an undefined error on the link when the Foo function is not defined.
Suppose you also define a global function foo in another file:
FOO2.C: int foo (int a) { return (a); } |
So in the example above, a reference to the Foo function address is then referred to in the foo2.c as the Foo function defined in the link. That is, the result of the ① call foo function is a=-a, because the Foo function inside the FOO.C is included, and the result of the ③ call is b=b, because it actually calls the Foo function inside the foo2.c.
The use of extern inline is very strange and rarely seen, but it has its practical value. First: It can act like a macro, you can replace an externally defined library function with the definition of an extern inline version within a file (provided that a call to it cannot be inline within a file); second: it allows a library function to be inline when it can be inline. As an example:
In the C file of a library function, define a generic version of the library function Libfunc:
LIB.C: void Libfunc () { ...; } |
And then within its header file, define (note is not a declaration.) A version that implements the same Exterin inline:
Lib.h: extern inline Libfunc () { ...; } |
The compiler uses the version of the extern inline in the header file when the other file uses the library function, as long as it has lib.h, where it can be expanded inline. In the event that it cannot be expanded (such as a function pointer reference), the compiler refers to the generic version of the standalone compilation in LIB.C. That seems like a function that can be inline externally, so this should be the origin of GCC's extern inline meaning. Note, however, that such use is costly: the implementation of the global functions in the C file must be identical to the implementation of the extern inline version in the header file. Otherwise, there is the problem of inconsistent function performance in the example above, both directly inline and indirectly called.
Important:the use of GCC's extern inline function is rather strange, and the scope of usage is very narrow: there is hardly any need to use it. There is no description of extern inline in C99, so it is not recommended that you use extern inline unless you explicitly understand the meaning of this usage and have sufficient reason to use it.
important : GCC will never generate a standalone sink code for an extern inline function
The extern inline function allows the same name as a global function to override externally defined global functions within a file scope
The extern inline function is very narrow in scope and behaves strangely, and is not recommended for use
2. The inline of C99
The following are the main descriptions of the C99 inline and gcc in different parts. For the same section, refer to the GCC inline instructions.
2.1. Static inline
Static inline with GCC (§ 1.1 "static inline").
2.2. Inline
The use of C99 's inline was quite puzzling. When a function defined as inline is not declared extern, its performance is somewhat similar to that of the extern inline in gcc (C99 inside this description is somewhat obscure, as in the original text):
If all of the file scope declarations for a function in a translation unit include the inline function specifier without E Xtern, then the definition in which translation is a inline definition. An inline definition does not provide a external definition for the function, and does not forbid a external definition In another translation. An inline definition provides the alternative to a external definition, which a translator could use to implement any call T o The function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition.
That is, if a inline function is not declared as extern within the file scope, the function is similar to GCC's extern inline in the file: When invoked in this file, the compiler is allowed to use the inline version defined in this document, But it also allows for external presence of global functions with the same name. It's just weird that C99 didn't specify whether the compiler had to use the inline version in this file, but let the compiler manufacturers decide for themselves, rather vague definitions.
If you declare this inline function as extern in a file, the performance of the inline function is consistent with GCC's inline: This function becomes a "external definition" (which can be simply understood as a global function): it can be called externally, And within the program can only exist a definition of such a name.
The following examples illustrate the characteristics of inline in C99:
Inline double Fahr (double t) { Return (9.0 * t)/5.0 + 32.0; } Inline double cels (double t) { Return (5.0 * (t-32.0))/9.0; } extern double Fahr (double); ① Double convert (int Is_fahr, double temp) { Return Is_fahr? Cels (temp): Fahr (temp); Ii } |
In the example above, the function Fahr is a global function: Because the Fahr is declared as extern at ①, it must be the version defined in this file when calling Fahr at ② (except that the compiler can inline the calls here). This function can also be called outside the file (stating that, like GCC's inline, the compiler generates a separate assembler for Fahr in this case).
The Cels function, which is not declared extern in the file scope, is the "inline definition" mentioned earlier, and it can actually only be used for the scope of this file (like a static function), There may also be an external global function with the same name as Cels. When Cels is invoked at ②, the compiler may choose to use the inline version in this file, or it may run to invoke an externally defined cels function (C99 does not specify the behavior at this time, but the compiler will certainly try to use the inline version defined in the file. Otherwise the inline function has no meaning in existence. From the performance here, the inline function, which is not declared as extern in C99, has been very similar to GCC's extern inline: the inline function in this document can be used as an alternative to external library functions.
important : the definition of the inline function in the C99 standard is ambiguous, and the inline function is not declared in the file scope as extern's performance is fundamentally different. If compared to GCC's inline function, a inline function declared as extern is essentially equivalent to the ordinary inline function of gcc, and a inline function that is not declared extern is essentially equivalent to GCC's extern inline function.
Because C99 's inline function is so bizarre, it is recommended that all inline functions create extern declarations in header files when used:
In the C file that defines the inline function, include this header file:
FOO.C: #include "foo.h" inline void foo () { ...; } |
In this way, both the inline rule of gcc and the C99 can get the exact same result: the Foo function is used inline within the foo.c file, and can be called directly externally as a normal global function.
2.3. extern inline
C99 did not see the use of extern inline.