Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikipediaThe Free Encyclopedia
Search

Inline (C and C++)

From Wikipedia, the free encyclopedia
(Redirected fromInline function)
Function in the C and C++ programming languages
This article is about inline functions in C and C++. For inline expansion more generally, seeInline expansion.
Not to be confused withInline assembler.
This article needs to beupdated. The reason given is:Meaning of inline changed in C++ (https://en.cppreference.com/w/cpp/language/inline). Please help update this article to reflect recent events or newly available information.(April 2019)

In theC andC++programming languages, aninline function is one qualified with thekeywordinline; this serves two purposes:

  1. It serves as acompiler directive that suggests (but does not require) that thecompiler substitute the body of the function inline by performinginline expansion, i.e. by inserting the function code at the address of each function call, thereby saving the overhead of a function call. In this respect it is analogous to theregisterstorage class specifier, which similarly provides an optimization hint.[1]
  2. The second purpose ofinline is to change linkage behavior; the details of this are complicated. This is necessary due to the C/C++ separate compilation + linkage model, specifically because the definition (body) of the function must be duplicated in alltranslation units where it is used, to allow inlining duringcompiling, which, if the function has externallinkage, causes a collision duringlinking (it violates uniqueness of external symbols). C and C++ (and dialects such as GNU C and Visual C++) resolve this in different ways.[1]

Example

[edit]

Aninline function can be written in C or C++ like this:

inlinevoidswap(int*m,int*n){inttmp=*m;*m=*n;*n=tmp;}

Then, a statement such as the following:

swap(&x,&y);

may be translated into (if the compiler decides to do the inlining, which typically requires optimization to be enabled):

inttmp=x;x=y;y=tmp;

When implementing asorting algorithm doing lots of swaps, this can increase the execution speed.

Standard support

[edit]

C++ andC99, but not its predecessorsK&R C andC89, have support forinline functions, though with different semantics. In both cases,inline 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 likeMicrosoft Visual C++ andGCC support an option that lets the compilers automatically inline any suitable function, even those not marked asinline functions. However, simply omitting theinline 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 becauseinline 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 (seestorage classes of inline functions).

Nonstandard extensions

[edit]

GNU C, as part of the dialect gnu89 that it offers, has support forinline as an extension to C89. However, the semantics differ from both those of C++ and C99. armcc in C90 mode also offersinline 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:

  • Microsoft Visual C++:__forceinline
  • gcc orclang:__attribute__((always_inline)) or__attribute__((__always_inline__)), the latter of which is useful to avoid a conflict with a user-defined macro namedalways_inline.

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:

  • inline is not respected by the compiler (ignored by compiler cost/benefit analyzer)
  • inlining results is necessary for boosting performance

For code portability, the following preprocessor directives may be used:

#ifdef _MSC_VER#define forceinline __forceinline#elif defined(__GNUC__)#define forceinline inline __attribute__((__always_inline__))#elif defined(__CLANG__)#if __has_attribute(__always_inline__)#define forceinline inline __attribute__((__always_inline__))#else#define forceinline inline#endif#else#define forceinline inline#endif

Storage classes of inline functions

[edit]

static inline 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 theinline qualifier and generate a function call in all C dialects and C++.

The effect of the storage classextern when applied or not applied toinline functions differs between the C dialects[2] and C++.[3]

C99

[edit]

In C99, a function definedinline will never, and a function definedextern inline 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.

Ifinline declarations are mixed withextern inline declarations or with unqualified declarations (ie., withoutinline qualifier or storage class), the translation unit must contain a definition (no matter whether unqualified,inline, orextern inline) and an externally visible function will be emitted for it.

A function definedinline requires exactly one function with that name somewhere else in the program which is either definedextern inline 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 theinline 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 theinline functions in header files and create one .c file per function, containing anextern inline 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 preventunreachable code from being added to the final executable if all uses of a function were inlined, it is advised[3] to put the object files of all such .c files with a singleextern inline function into astatic library file, typically withar rcs, 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 frominline functions to otherinline functions will be resolved by the linker automatically (thes option inar rcs ensures this).

An alternative solution is to use link time optimization instead of a library. gcc provides the flag-Wl,--gc-sections to omit sections in which all functions are unused. This will be the case for object files containing the code of a single unusedextern inline function. However, it also removes any and all other unused sections from all other object files, not just those related to unusedextern inline 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 allextern inline functions instead of one .c file per function. Then the file has to be compiled with-fdata-sections -ffunction-sections. 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 asstatic inline instead ofinline in header files.[2] 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 asstatic inline in a header file will yield different values in different translation units. Therefore,static inline 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

[edit]

gnu89 semantics ofinline andextern inline are essentially the exact opposite of those in C99,[4] with the exception that gnu89 permits redefinition of anextern inline function as an unqualified function, while C99inline does not.[5] Thus, gnu89extern inline without redefinition is like C99inline, and gnu89inline is like C99extern inline; in other words, in gnu89, a function definedinline will always and a function definedextern inline 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 asextern and always if defined without. The rationale for C99, in contrast, is that it would beastonishing if usinginline 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 gnu89inline semantics even when-std=c99 was explicitly specified.[6] With version 5,[5] gcc switched from gnu89 to the gnu11 dialect, effectively enabling C99inline semantics by default. To use gnu89 semantics instead, they have to be enabled explicitly, either with-std=gnu89 or, to only affect inlining,-fgnu89-inline, or by adding thegnu_inline attribute to allinline declarations. To ensure C99 semantics, either-std=c99,-std=c11,-std=gnu99 or-std=gnu11 (without-fgnu89-inline) can be used.[3]

C++

[edit]

In C++, a function definedinline will, if required, emit a function shared among translation units, typically by putting it into the common section of theobject file for which it is needed. The function must have the same definition everywhere, always with theinline qualifier. In C++,extern inline is the same asinline. 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 whetherextern is specified or not.

Theinline qualifier is automatically added to a function defined as part of a class definition.

armcc

[edit]

armcc in C90 mode providesextern inline andinline semantics that are the same as in C++: Such definitions will emit a function shared among translation units if required. In C99 mode,extern inline always emits a function, but like in C++, it will be shared among translation units. Thus, the same function can be definedextern inline in different translation units.[7] This matches the traditional behavior of Unix C compilers[8] for multiple non-extern definitions of uninitialized global variables.

Restrictions

[edit]

Taking the address of aninline function requires code for a non-inlined copy of that function to be emitted in any case.

In C99, aninline orextern inline function must not accessstatic global variables or define non-conststatic local variables.const static 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. Onlystatic inline definitions can reference identifiers with internal linkage without restrictions; those will be different objects in each translation unit. In C++, bothconst and non-conststatic locals are allowed and they refer to the same object in all translation units.

GCC cannot inline functions if[3]

  1. They arevariadic,
  2. Usealloca,
  3. Use computedgoto,
  4. Use nonlocalgoto,
  5. Usenested functions,
  6. Usesetjmp,
  7. Use__builtin_longjmp,
  8. Use__builtin_return, or
  9. Use__builtin_apply_args.

Based on Microsoft Specifications at MSDN, MS Visual C++ cannot inline (not even with__forceinline), if

  1. The function or its caller is compiled with /Ob0 (the default option for debug builds).
  2. The function and the caller use different types ofexception handling (C++ exception handling in one, structured exception handling in the other).
  3. The function has avariable argument list.
  4. The function usesinline assembly, unless compiled with /Og, /Ox, /O1, or /O2.
  5. The function isrecursive and not accompanied by#pragma inline_recursion(on). With the pragma, recursive functions are inlined to a default depth of 16 calls. To reduce the inlining depth, useinline_depth pragma.
  6. The function isvirtual and is called virtually. Direct calls to virtual functions can be inlined.
  7. The program takes the address of the function and the call is made via the pointer to the function. Direct calls to functions that have had their address taken can be inlined.
  8. The function is also marked with the naked__declspec modifier.

Problems

[edit]
See also:Inline expansion § Effect on performance

Besides the problems with inline expansion in general (seeInline expansion § Effect on performance),inline functions as a language feature may not be as valuable as they appear, for a number of reasons:

  • Often, a compiler is in a better position than a human to decide whether a particular function should be inlined. Sometimes the compiler may not be able to inline as many functions as the programmer indicates.
  • An important point to note is that the code (of theinline function) gets exposed to its client (the calling function).
  • As functions evolve, they may become suitable for inlining where they were not before, or no longer suitable for inlining where they were before. While inlining or un-inlining a function is easier than converting to and from macros, it still requires extra maintenance which typically yields relatively little benefit.
  • Inline functions used in proliferation in native C-based compilation systems can increase compilation time, since the intermediate representation of their bodies is copied into each call site.
  • The specification ofinline in C99 requires exactly one external definition of the function, if it is used somewhere. If such a definition wasn't provided by the programmer, that can easily lead to linker errors. This can happen with optimization turned off, which typically prevents inlining. Adding the definitions, on the other hand, can cause unreachable code if the programmer does not carefully avoid it, by putting them in a library for linking, using link time optimization, orstatic inline.
  • In C++, it is necessary to define aninline function in every module (translation unit) that uses it, whereas an ordinary function must be defined in only a single module. Otherwise it would not be possible to compile a single module independently of all other modules. Depending on the compiler, this may cause each respective object file to contain a copy of the function's code, for each module with some use that could not be inlined.
  • Inembedded software, oftentimes certain functions need to be placed in certain code sections by use of special compiler instructions such as "pragma" statements. Sometimes, a function in one memory segment might need to call a function in another memory segment, and if inlining of the called function occurs, then the code of the called function might end up in a segment where it shouldn't be. For example, high-performance memory segments may be very limited in code space, and if a function belonging in such a space calls another large function that is not meant to be in the high-performance section and the called function gets inappropriately inlined, then this might cause the high-performance memory segment to run out of code space. For this reason, sometimes it is necessary to ensure that functions donot become inlined.

Quotes

[edit]

A function declaration ... with aninline specifier declares an inline function. Theinline 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.

— ISO/IEC 14882:2011, the current C++ standard, section 7.1.2

A function declared with aninline 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 anothertranslation 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.

— ISO 9899:1999(E), the C99 standard, section 6.7.4

See also

[edit]

References

[edit]
  1. ^abMeyers, Randy (July 1, 2002)."The New C: Inline Functions".{{cite journal}}:Cite journal requires|journal= (help)
  2. ^ab"Inline Functions in C".
  3. ^abcd"Using the GNU Compiler Collection (GCC): Inline".
  4. ^"Josef "Jeff" Sipek » GNU inline vs. C99 inline".
  5. ^ab"Porting to GCC 5 - GNU Project".
  6. ^"Ian Lance Taylor - Clean up extern inline".
  7. ^"Documentation – Arm Developer".
  8. ^gcc manual page, description of-fno-common

External links

[edit]
Retrieved from "https://en.wikipedia.org/w/index.php?title=Inline_(C_and_C%2B%2B)&oldid=1317685256"
Category:
Hidden categories:

[8]ページ先頭

©2009-2026 Movatter.jp