1. inline functions in C Language
This article introduces the differences between inline usage in GCC and c99. When using the inline attribute, pay attention to the following two points: the inline keyword is only described in the definition of the function used in the GCC reference document, it does not mention whether it can be used in function declaration (declare ).
From the perspective of the role of inline, it should be useless to put in the function declaration: inline only affects the compilation behavior of the function in the Translation Unit (which can be simply understood as the C source code file, as long as the range is exceeded, the inline attribute has no effect. Therefore, the inline keyword should not appear in the function declaration. It does not have any effect. Sometimes it may cause compilation errors (including sys/compiler. h, the part with the inline keyword in the Declaration usually cannot be compiled );
The Inline keyword is only recommended for the compiler to perform inline expansion, rather than forcing. In the GCC compiler, if the compilation optimization is set to-O0, even inline functions will not be expanded inline unless forced inline (_ attribute _ (always_inline) is set ))) attribute.
1.1 GCC inline
GCC has made its own extensions to the inline of C language, and its behavior is quite different from that in the c99 standard.
1.1.1 static inline
The static inline definition of GCC is easy to understand: You can regard it as a static function and add the inline attribute. Most of the functions are the same as normal static functions, but when calling such functions, GCC will expand and compile the code at its call without generating an independent assembly code for this function. Except for the following situations:
When the function address is used. For example, the function is indirectly called through the function pointer. In this case, you have to generate an independent assembly code for the static inline function, otherwise it does not have its own address.
In other situations, for example, the function itself has the behavior of Recursion Calling itself.
The static inline function is the same as the static function. Its definition range is local, that is, multiple definitions with the same name can be defined in the Program (as long as they are not in the same file ).
Note:
The static inline of GCC is consistent with the static inline of c99. Therefore, this definition can be safely used without compatibility issues.
Key points:
Compared with static functions, static inline of GCC only recommends that the compiler conduct Inline expansion during calling;
GCC will not specifically generate Independent Assembly codes for the static inline function unless it is necessary to generate the code (such as using function pointers and recursive calls );
The static inline function of GCC can only work within the file range.
1.1.2 inline
Compared with c99's inline, GCC's inline is easier to understand: it can be considered as a common global function with the inline attribute. That is, in the file where the definition is located, it is consistent with static inline: it will be expanded and compiled inline when it can be expanded. But in order to be able to call it outside the file, GCC will certainly generate an independent assembly code for it for external calls. That is to say, it is similar to a normal extern function from outside the file. For example:
Foo. C:
/* An inline function Foo () is defined here ()*/
Inline Foo (){
...; <-The compiler will generate Independent Assembly codes for Foo () like non-inline functions
}
Void func1 (){
Foo (); <-in the same file, Foo () may be compiled inline by the compiler rather than calling the assembly code generated above.
} When Foo () is called in another file, the assembly code generated in the above file is called directly:
Bar. C:
Extern Foo (); <-declare Foo (). Note that the inline keyword cannot be included in the declaration.
Void func2 (){
Foo (); <-here is the assembly code generated by the call function for Foo () in Foo. C.
} Important
Although the inline function of GCC is well understood, it is very different from the inline function of c99. Pay attention to the description of c99 inline (section 2.2 "inline") and how to use the inline function in both GCC and c99.
Key points:
Compared with normal extern functions, the inline function of GCC only recommends that the compiler conduct Inline expansion when calling the same file;
GCC will certainly generate an independent assembly code for the inline function so that it can be called outside this file. In other files, the inline function is similar to the normal extern function;
The Inline Function of GCC is global: it can be expanded inline as an inline function in the file, but can be called outside the file.
1.1.3 extern inline
Both static inline and inline of GCC are well understood: they all seem to have added inline attributes to common functions. However, this extern inline cannot be simply understood as an extern Function + inline attribute. In fact, the GCC extern inline is very strange: an extern inline function will only be inline, but will never generate an independent assembly code! Even a pointer application or recursive call won't let the compiler generate an assembly code for it. In this case, the call to this function will be processed as an external reference. In addition, the extern inline function can have the same name as the external function. That is, if an external-defined global library function exists, defining an extern inline function with the same name is also valid. The following example describes the features of extern inline:
Foo. C:
Extern inline
Int Foo (int)
{
Return (-);
}
Void func1 ()
{
...;
A = Foo (a); ①
P_foo = Foo; ②
B = p_foo (B); ③
} In this file, GCC will not generate the assembly code of the foo function. In the call point ① In func1, the compiler will inline compile the foo function defined above, which is similar to the ordinary inline function. This is because such a call can be used for inline processing. In section ②, the address of the foo function is referenced. But note: the compiler will never generate Independent Assembly codes for the extern inline function! Therefore, when a function address is required to be unavailable, the compiler has to process it as an external reference and link it to the external Foo function (fill in the address of the external function) during the link ). In this case, if the global Foo function is not defined externally, an undefined Foo function error will be generated during the link.
Assume that a global function foo is also defined in another file:
Foo2.c:
Int Foo (int)
{
Return ();
} In the above example, the next reference to the foo function address will be directed to the foo function defined in foo2.c at the link. That is to say: ① the result of calling the foo function is a =-A, because it is inline with Foo. the Foo function in C; and ③ The call result is B = B, because it actually calls the foo function in foo2.c!
The use of extern inline is very strange and rare, but it still has practical value. First, it can behave like a macro, you can replace the library function of the external definition with the definition of the extern inline version in the file (the premise is that the file cannot be called inline); Second: it allows a library function to be used inline whenever possible. For example:
In the c file of a library function, define a common version of library function libfunc:
Lib. C:
Void libfunc ()
{
...;
} Then define it in the header file (note that it is not a declaration !) A version that implements the same exterin inline:
Lib. h:
Extern inline libfunc ()
{
...;
} When other files need to use this library function, the compiler will use the extern inline version in the header file whenever Lib. H is included. When expansion fails (function pointer reference, etc.), the compiler will reference the self-compiled normal version in Lib. C. That is, it seems to be a function that can be inline externally, so this should be the origin of GCC's extern inline meaning.
However, it is worth noting that the implementation of global functions in the C file must be exactly the same as that in the extern inline version in the header file. Otherwise, the function performance will be inconsistent during direct and indirect calls in the previous example.
Important
The usage of the GCC extern inline function is quite strange, and the scope of use is also very narrow: there is almost no need to use it.
There is no such description about extern inline in c99, so we do not recommend that you use extern inline unless you have understood the meaning of this usage and have enough reason to use it!
Key points:
GCC will never generate Independent Assembly codes for functions of extern inline.
The extern inline function can have the same name as the global function. It can replace the externally defined global function within the file range.
The application scope of the extern inline function is very narrow and the behavior is strange. It is not recommended to use
1.2 c99 inline
The following describes the inline of c99 and the different parts of GCC. For the same part, refer to the instructions of GCC inline.
1.2.1 static inline
Same as static inline of GCC (Section 1.1 "static inline ").
1.2.2 inline
The use of c99 inline is rather confusing. When a function defined as inline is not declared as extern, it is a bit similar to extern inline in GCC (the description in c99 is a bit obscure, the original article is as follows ):
If all of the File Scope declarations for a function in a Translation Unit include the inline function specifier without extern, then the definition in that translation unit is an inline definition. an inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. an inline definition provides an alternative to an external definition, which a translator may use to implement any call to 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 to say, if an inline function is not declared as extern within the file range, the expression of this function in the file is similar to the extern inline of GCC: during calls in this file, the compiler is allowed to use the inline version defined in this file, but global functions with the same name can also exist externally. It is strange that c99 does not specify whether the compiler must use this inline version in this file. Instead, it allows the compiler manufacturer to decide on its own.
If the inline function is declared as extern in the file, the expression of the inline function is the same as that of the GCC inline function: this function becomes an "external definition" (which can be simply understood as a global function): it can be called externally, and only one such name can be defined in the program.
The following example describes the features 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); ②
} In the above example, the Fahr function is a global function: Because Fahr is declared as extern at ①, therefore, when you call Fahr at ②, you must use the version defined in this file (except that the compiler can expand the call here in line ). This function can also be called outside the file (it indicates that, like the GCC inline, the compiler will generate an independent assembly code for Fahr in this case ).
The CELS function is called "inline definition" because it is not declared as extern within the file range ", at this time, it can only act on the scope of this file (just like a static function). There may also be a global function with the same name as CELS. When you call CELS at ②, the compiler may choose to use the inline version in this file, or it may run to call the external defined CELS function (c99 does not specify the behavior at this time, however, the compiler will always try to use the inline version defined in the file, otherwise the inline function will have no meaning ). Here, we can see that the inline function that is not declared as extern in c99 is very similar to the extern inline function in GCC: the inline function in this file can be used as an alternative to the external library function.
Important
The inline function defined in the c99 standard is vague, and whether the inline function is declared as extern within the file range is essentially different. If compared with the inline function of GCC, an inline function declared as extern is basically equivalent to the normal inline function of GCC; an inline function that is not declared as extern is basically equivalent to the extern inline function of GCC.
Because the inline function of c99 is so weird, we recommend that you create an extern Declaration for all inline functions in the header file:
Foo. h:
Extern Foo (); and include this header file in the C file that defines the inline function:
Foo. C:
# Include "foo. H"
Inline void Foo ()
{
...;
} In this way, both the GCC inline rule and the c99 rule can get the same result: the foo function will be in Foo. the C file is used inline, and can be called externally just like a common global function.
1.2.3 extern inline
The use of extern inline is not seen in c99.