Reputation: 131646
Consider the use of inline
in C99, with various options (extern'ing, static inline etc), as described here, for example.
I don't understand why the C standard does not allow for just using
void inline foo() { do_stuff(); }
in a common header file, and for that to work everywhere. Why do I have to add static
? Isn't what I want clear enough already?
Upvotes: 1
Views: 565
Reputation: 320531
...C standard does not allow for just using...
That's completely wrong. Your question is based on some incorrect/outdated/compiler specific premise, which has nothing to do with C standard. In C language you don't need static
when putting inline
function in header file. An inline
definition without an explicitly specified extern
keyword does not form an external definition for that function. For that reason inline
definition without static
cannot trigger any multiple-definition-related errors (if that's what you are afraid of).
Moreover, the link that you posted clearly says that C standard does not say anything implied in your question. It says that GCC compiler implements inline
differently from what's required by C standard (probably referring to an older version of GCC).
In other words, from C language point of view you can (and should) put
inline void foo() { do_stuff(); }
in the header file. No static
required.
Upvotes: 0
Reputation: 1822
From the gcc site:
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.
What does it mean for you. You cannot define the inline function in the header since it will mean that it will be defined from different translation units (.c files that include it).
Once it is defined static inline
then each c file that includes the header will have its own copy of the function.
EDIT
gcc behaves correctly. Inline functions were added to the standard with the introduction of C99. The standard is somewhat ambiguous and states:
Any function with internal linkage can be an inline function. For a function with external linkage, the following restrictions apply: If a function is declared with an inline function specifier, then it shall also be defined in the same translation unit. 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.
What it actually means is that when the compiler sees the inline keyword cannot know if the function was already defined in another translation unit (This will be known only during linking). Now most compilers gcc included will not inline a function without optimizations turned on. So if you try to use an inline function when compiling with -O0 the compiler issues a real call to the function (It assumes it is defined in a another file then the one it is currently compiling). Now when the linker encounters the call it tries to find the function in all compiled objects but fails (because the compiler didn't create a body for the function neither did it inline it - the standard says it doesn't have to create a body for the function and that it can assume there is a definition some where). This is why you get the error: undefined reference to f
when you link your project. This is the correct behavior when compiling with -std=c99 onward. It also means that if you want an inline function to have abody you must declare it external only once BUT you must also provide the definition within the same translation unit you declared the function with extrnal linkage.
So in order to get your code to work correctly according to the standard you should do the following:
in the h file just do as you would expect.
inline void f(){ /*DO SOMETHING*/}
And in just one of your code files (.c files) you do:
extern inline void f();
What happens is that now the compiler encounters in just one translation unit both body definition (taken from the header) and a declaration that says it should exist an external definition somewhere and in accordance with the standard creates one for the function.
So the standard says that any function with internal linkage can be declared inline and that the compiler should generate a body for it. In C a function is considered to have internal linkage only when adding the static keyword.
This is why static inline void f()
works. Without the static keyword the compiler assumes that the function has external linkage and that is why just specifying inline void f()
without also adding extern inline void f()
in just one source file will not work.
Upvotes: 1