Inline c что это

от admin

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

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

  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?

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 , in which I see no difference with just static .

6 Answers 6

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

inline functions:

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.

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.

non-static inline and Static inline

Again referring to 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:

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.

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.

  1. For inline void f(void)<> , inline definition 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 inline definition 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.

WedaPashi's user avatar

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

static inline void f(void) <> has no practical difference with 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.

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?

This is explained by this answer and also this thread.

In ISO C and C++, you can freely use inline void f(void) <> in header files — although for different reasons!

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 inline function, then the compiler sorts it out and picks one of them.

extern inline void f(void); in a .c file in ISO C is meant to be paired with the use of inline void f(void) <> in header files. It causes the external definition of 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 f links to the external definition or not).

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

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

To complicate things further, GNU C++ allows you to write static inline an extern inline in C++ code. I wouldn’t like to guess on what that does exactly

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

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.

In GNU C, plain inline behaves differently to ISO C. It actually emits an externally visible definition, so having a .h file with a plain inline function included from two translation units causes undefined behaviour.

So if the coder wants to supply the inline optimization hint in GNU C, then static inline is required. Since static inline works 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.

, 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.

From 6.7.4 Function specifiers in C11 specs

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.

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) <> .

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

inline void f(void) <> in C doesn’t work as the C++ way. How does it work in 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).

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

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

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.

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

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

Читать:
Checking file system on d как убрать

If you understand where they come from then you’ll understand why they are there.

Both "inline" and "const" are C++ innovations that were eventually retrofit into C. One of the design goals implicit in these innovations, as well as later innovations, like template’s and even lambda’s, was to carve out the most common use-cases for the pre-processor (particularly, of "#define"), so as to minimize the use of and need for the pre-processor phase.

The occurrence of a pre-processor phase in a language severely limits the ability to provide transparency in the analysis of and translation from a language. This turned what ought to have been easy translation shell scripts into more complicated programs, such as "f2c" (Fortran to C) and the original C++ compiler "cfront" (C++ to C); and to a lesser degree, the "indent" utility. If you’ve ever had to deal with the translation output of convertors like these (and we have) or with actually making your own translators, then you’ll know how much of an issue this is.

The "indent" utility, by the way, balks on the whole issue and just wings it, compromising by just treating macros calls as ordinary variables or function calls, and passing over "#include"’s. The issue will also arise with other tools that may want to do source-to-source conversion/translation, like automated re-engineering, re-coding and re-factoring tools; that is, things that more intelligently automate what you, the programmer, do.

So, the ideal is to reduce dependency on the pre-processor phase to a bare minimum. This is a goal that is good in its own right, independently of how the issue may have been encountered in the past.

Over time, as more and more of the use-cases became known and even standardized in their usage, they were encapsulated formally as language innovations.

One common use-case of "#define" to create manifest constants. To a large extent, this can now be handled be the "const" keyword and (in C++) "constexpr".

Another common use-case of "#define" is to create functions with macros. Much of this is now encapsulated by the "inline" function, and that’s what it’s meant to replace. The "lambda" construct takes this a step further, in C++.

Both "const" and "inline" were present in C++ from the time of its first external release — release E in February 1985. (We’re the ones who transcribed and restored it. Before 2016, it only existed as a badly-clipped printout of several hundred pages.)

Other innovations were added later, like "template" in version 3.0 of cfront (having been accepted in the ANSI X3J16 meeting in 1990) and the lambda construct and "constexpr" much more recently.

inline function specifier

The intent of the inline specifier is to serve as a hint for the compiler to perform optimizations, such as function inlining, which usually require the definition of a function to be visible at the call site. The compilers can (and usually do) ignore presence or absence of the inline specifier for the purpose of optimization.

If the compiler performs function inlining, it replaces a call of that function with its body, avoiding the overhead of a function call (placing data on stack and retrieving the result), which may result in a larger executable as the code for the function has to be repeated multiple times. The result is similar to function-like macros, except that identifiers and macros used in the function refer to the definitions visible at the point of definition, not at the point of call.

Regardless of whether inlining takes place, the following semantics of inline functions are guaranteed:

Any function with internal linkage may be declared static inline with no other restrictions.

A non-static inline function cannot define a non-const function-local static and cannot refer to a file-scope static.

If a non-static function is declared inline , then it must be defined in the same translation unit. The inline definition that does not use extern is not externally visible and does not prevent other translation units from defining the same function. This makes the inline keyword an alternative to static for defining functions inside header files, which may be included in multiple translation units of the same program.

If a function is declared inline in some translation units, it does not need to be declared inline everywhere: at most one translation unit may also provide a regular, non-inline non-static function, or a function declared extern inline . This one translation unit is said to provide the external definition. In order to avoid undefined behavior, one external definition must exist in the program if the name of the function with external linkage is used in an expression, see one definition rule.

The address of an inline function with external linkage is always the address of the external definition, but when this address is used to make a function call, it’s unspecified whether the inline definition (if present in the translation unit) or the external definition is called. The static objects defined within an inline definition are distinct from the static objects defined within the external definition:

A C program should not depend on whether the inline version or the external version of a function is called, otherwise the behavior is unspecified.

[edit] Keywords

[edit] Notes

The inline keyword was adopted from C++, but in C++, if a function is declared inline , it must be declared inline in every translation unit, and also every definition of an inline function must be exactly the same (in C, the definitions may be different, and depending on the differences only results in unspecified behavior). On the other hand, C++ allows non-const function-local statics and all function-local statics from different definitions of an inline function are the same in C++ but distinct in C.

спецификатор встроенной функции

Назначение спецификатора inline состоит в том, чтобы служить подсказкой для компилятора для выполнения оптимизаций, таких как встраивание функций , которые обычно требуют, чтобы определение функции было видно на месте вызова. Компиляторы могут (и обычно так и делают) игнорировать наличие или отсутствие inline спецификатора в целях оптимизации.

Если компилятор выполняет встраивание функции, он заменяет вызов этой функции своим телом, избегая накладных расходов на вызов функции (размещение данных в стеке и получение результата), что может привести к увеличению размера исполняемого файла, поскольку код для функции имеет повторяться несколько раз. Результат похож на функционально-подобные макросы , за исключением того, что идентификаторы и макросы, используемые в функции, относятся к определениям, видимым в точке определения, а не в точке вызова.

Независимо от того,происходит ли встраивание,гарантируется следующая семантика функций встраивания:

Любая функция с внутренней связью может быть объявлена static inline без каких-либо других ограничений.

Нестатическая встроенная функция не может определить неконстантную статическую функцию и не может ссылаться на статическую файловую область.

Если нестатическая функция объявлена inline , то она должна быть определена в той же единице перевода. Встроенное определение, которое не использует extern , не видимо снаружи и не мешает другим единицам перевода определять ту же функцию. Это делает ключевое слово inline альтернативным static для определения функций внутри заголовочных файлов, которые могут быть включены в несколько модулей перевода одной и той же программы.

Если функция объявлена inline в некоторых единицах перевода, ее не нужно объявлять inline везде: максимум одна единица перевода может также предоставлять обычную, не встроенную нестатическую функцию или функцию, объявленную extern inline . Говорят, что эта единица перевода обеспечивает external definition . Во избежание неопределенного поведения в программе должно существовать одно внешнее определение, если в выражении используется имя функции с внешней связью, см. одно правило определения .

Адрес встроенной функции с внешней связью всегда является адресом внешнего определения,но когда этот адрес используется для вызова функции,не определено,является ли адрес функции inline definition (если присутствует в блоке перевода) или external definition называется.Статические объекты,определенные в определении inline,отличаются от статических объектов,определенных во внешнем определении:

Программа на языке Си не должна зависеть от того,вызывается ли встроенная или внешняя версия функции,иначе поведение будет неопределенным.

Keywords

Notes

Ключевое слово inline было заимствовано из C++, но в C++, если функция объявлена inline , она должна быть объявлена inline в каждой единице перевода, а также каждое определение встроенной функции должно быть точно таким же (в C определения могут быть разными). отличается, и в зависимости от различий приводит только к неопределенному поведению). С другой стороны, C++ допускает неконстантную локальную статику функции, и все локальные функции статики из разных определений встроенной функции одинаковы в C++, но различны в C.

Inline c что это

Compiler Error:

Why this error happened?

This is one of the side effect of GCC the way it handle inline function. When compiled, GCC performs inline substitution as the part of optimisation. So there is no function call present (foo) inside main. Please check below assembly code which compiler will generate.

Normally GCC’s file scope is “not extern linkage”. That means inline function is never ever provided to the linker which is causing linker error, mentioned above.

How to remove this error?

To resolve this problem use “static” before inline. Using static keyword forces the compiler to consider this inline function in the linker, and hence the program compiles and run successfully.

Related Posts