Contents
Inline function
In the C and C++ programming languages, an inline function is one qualified with the keyword ; this serves two purposes:
Example
An function can be written in C or C++ like this: Then, a statement such as the following: may be translated into (if the compiler decides to do the inlining, which typically requires optimization to be enabled): When implementing a sorting algorithm doing lots of swaps, this can increase the execution speed.
Standard support
C++ and C99, but not its predecessors K&R C and C89, have support for functions, though with different semantics. In both cases, does not force inlining; the compiler is free to choose not to inline the function at all, or only in some cases. Different compilers vary in how complex a function they can manage to inline. Mainstream C++ compilers like Microsoft Visual C++ and GCC support an option that lets the compilers automatically inline any suitable function, even those not marked as functions. However, simply omitting the keyword to let the compiler make all inlining decisions is not possible, since the linker will then complain about duplicate definitions in different translation units. This is because not only gives the compiler a hint that the function should be inlined, it also has an effect on whether the compiler will generate a callable out-of-line copy of the function (see storage classes of inline functions).
Nonstandard extensions
GNU C, as part of the dialect gnu89 that it offers, has support for as an extension to C89. However, the semantics differ from both those of C++ and C99. armcc in C90 mode also offers as a non-standard extension, with semantics different from gnu89 and C99. Some implementations provide a means by which to force the compiler to inline a function, usually by means of implementation-specific declaration specifiers: Indiscriminate uses of that can result in larger code (bloated executable file), minimal or no performance gain, and in some cases even a loss in performance. Moreover, the compiler cannot inline the function in all circumstances, even when inlining is forced; in this case both gcc and Visual C++ generate warnings. Forcing inlining is useful if: For code portability, the following preprocessor directives may be used:
Storage classes of inline functions
has the same effects in all C dialects and C++. It will emit a locally visible (out-of-line copy of the) function if required. Regardless of the storage class, the compiler can ignore the qualifier and generate a function call in all C dialects and C++. The effect of the storage class when applied or not applied to functions differs between the C dialects and C++.
C99
In C99, a function defined will never, and a function defined will always, emit an externally visible function. Unlike in C++, there is no way to ask for an externally visible function shared among translation units to be emitted only if required. If declarations are mixed with declarations or with unqualified declarations (ie., without qualifier or storage class), the translation unit must contain a definition (no matter whether unqualified, , or ) and an externally visible function will be emitted for it. A function defined requires exactly one function with that name somewhere else in the program which is either defined or without qualifier. If more than one such definition is provided in the whole program, the linker will complain about duplicate symbols. If, however, it is lacking, the linker does not necessarily complain, because, if all uses could be inlined, it is not needed. But it may complain, since the compiler can always ignore the qualifier and generate calls to the function instead, as typically happens if the code is compiled without optimization. (This may be the desired behavior, if the function is supposed to be inlined everywhere by all means, and an error should be generated if it is not.) A convenient way is to define the functions in header files and create one .c file per function, containing an declaration for it and including the respective header file with the definition. It does not matter whether the declaration is before or after the include. To prevent unreachable code from being added to the final executable if all uses of a function were inlined, it is advised to put the object files of all such .c files with a single function into a static library file, typically with , then link against that library instead of the individual object files. That causes only those object files to be linked that are actually needed, in contrast to linking the object files directly, which causes them to be always included in the executable. However, the library file must be specified after all the other object files on the linker command line, since calls from object files specified after the library file to the functions will not be considered by the linker. Calls from functions to other functions will be resolved by the linker automatically (the option in ensures this). An alternative solution is to use link time optimization instead of a library. gcc provides the flag to omit sections in which all functions are unused. This will be the case for object files containing the code of a single unused function. However, it also removes any and all other unused sections from all other object files, not just those related to unused functions. (It may be desired to link functions into the executable that are to be called by the programmer from the debugger rather than by the program itself, eg., for examining the internal state of the program.) With this approach, it is also possible to use a single .c file with all functions instead of one .c file per function. Then the file has to be compiled with. However, the gcc manual page warns about that, saying "Only use these options when there are significant benefits from doing so." Some recommend an entirely different approach, which is to define functions as instead of in header files. Then, no unreachable code will be generated. However, this approach has a drawback in the opposite case: Duplicate code will be generated if the function could not be inlined in more than one translation unit. The emitted function code cannot be shared among translation units because it must have different addresses. This is another drawback; taking the address of such a function defined as in a header file will yield different values in different translation units. Therefore, functions should only be used if they are used in only one translation unit, which means that they should only go to the respective .c file, not to a header file.
gnu89
gnu89 semantics of and are essentially the exact opposite of those in C99, with the exception that gnu89 permits redefinition of an function as an unqualified function, while C99 does not. Thus, gnu89 without redefinition is like C99 , and gnu89 is like C99 ; in other words, in gnu89, a function defined will always and a function defined will never emit an externally visible function. The rationale for this is that it matches variables, for which storage will never be reserved if defined as and always if defined without. The rationale for C99, in contrast, is that it would be astonishing if using would have a side-effect—to always emit a non-inlined version of the function—that is contrary to what its name suggests. The remarks for C99 about the need to provide exactly one externally visible function instance for inlined functions and about the resulting problem with unreachable code apply mutatis mutandis to gnu89 as well. gcc up to and including version 4.2 used gnu89 semantics even when was explicitly specified. With version 5, gcc switched from gnu89 to the gnu11 dialect, effectively enabling C99 semantics by default. To use gnu89 semantics instead, they have to be enabled explicitly, either with or, to only affect inlining, , or by adding the attribute to all declarations. To ensure C99 semantics, either, , or (without ) can be used.
C++
In C++, a function defined will, if required, emit a function shared among translation units, typically by putting it into the common section of the object file for which it is needed. The function must have the same definition everywhere, always with the qualifier. In C++, is the same as. The rationale for the C++ approach is that it is the most convenient way for the programmer, since no special precautions for elimination of unreachable code must be taken and, like for ordinary functions, it makes no difference whether is specified or not. The qualifier is automatically added to a function defined as part of a class definition.
armcc
armcc in C90 mode provides and semantics that are the same as in C++: Such definitions will emit a function shared among translation units if required. In C99 mode, always emits a function, but like in C++, it will be shared among translation units. Thus, the same function can be defined in different translation units. This matches the traditional behavior of Unix C compilers for multiple non- definitions of uninitialized global variables.
Restrictions
Taking the address of an function requires code for a non-inlined copy of that function to be emitted in any case. In C99, an or function must not access global variables or define non- local variables. local variables may or may not be different objects in different translation units, depending on whether the function was inlined or whether a call was made. Only definitions can reference identifiers with internal linkage without restrictions; those will be different objects in each translation unit. In C++, both and non- locals are allowed and they refer to the same object in all translation units. gcc cannot inline functions if Based on Microsoft Specifications at MSDN, MS Visual C++ cannot inline (not even with ), if
Problems
Besides the problems with inline expansion in general (see ), functions as a language feature may not be as valuable as they appear, for a number of reasons:
Quotes
"A function declaration... with an inline specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected." "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. The extent to which such suggestions are effective is implementation-defined (footnote: For example, an implementation might never perform inline substitution, or might only perform inline substitutions to calls in the scope of an inline declaration.) ...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."
This article is derived from Wikipedia and licensed under CC BY-SA 4.0. View the original article.
Wikipedia® is a registered trademark of the
Wikimedia Foundation, Inc.
Bliptext is not
affiliated with or endorsed by Wikipedia or the
Wikimedia Foundation.