I am trying to implement a global singleton variable in the header-only library in C (not C++). So after searching on this forum and elsewhere, I came across a variation of Meyer's singleton that I am adapting to C here:
/* File: sing.h */
#ifndef SING_H
#define SING_H
inline int * singleton()
{
static int foo = 0;
return &foo;
}
#endif
Notice that I am returning a pointer because C lacks & referencing available in C++, so I must work around it.
OK, now I want to test it, so here is a simple test code:
/* File: side.h */
#ifndef SIDE_H
#define SIDE_H
void side();
#endif
/*File: side.c*/
#include "sing.h"
#include <stdio.h>
void side()
{
printf("%d\n",*(singleton()));
}
/*File: main.c*/
#include "sing.h"
#include "side.h"
#include <stdio.h>
int main(int argc, char * argv[])
{
/* Output default value - expected output: 0 */
printf("%d\n",*(singleton()));
*(singleton()) = 5;
/* Output modified value - expected output: 5 */
printf("%d\n",*(singleton()));
/* Output the same value from another module - expected output: 5*/
side();
return 0;
}
Compiles and runs fine in MSVC in C mode (also in C++ mode too, but that's not the topic). However, in gcc it outputs two warnings (warning: ‘foo’ is static but declared in inline function ‘singleton’ which is not static), and produces an executable which then segfaults when I attempt to run it. The warning itself kind of makes sense to me (in fact, I am surprised I don't get it in MSVC), but segfault kind of hints at the possibility that gcc never compiles foo as a static variable, making it a local variable in stack and then returns expired stack address of that variable.
I tried declaring the singleton as extern inline, it compiles and runs fine in MSVC, results in linker error in gcc (again, I don't complain about linker error, it is logical).
I also tried static inline (compiles fine in both MSVC and gcc, but predictably runs with wrong output in the third line because the side.c translation unit now has its own copy of singleton.
So, what am I doing wrong in gcc? I have neither of these problems in C++, but I can't use C++ in this case, it must be straight C solution.
I could also accept any other form of singleton implementation that works from header-only library in straight C in both gcc and MSVC.
I am trying to implement a global singleton variable in the header-only library in C (not C++).
By "global", I take you to mean "having static storage duration and external linkage". At least, that's as close as C can come. That is also as close as C can come to a "singleton" of a built-in type, so in that sense, the term "global singleton" is redundant.
Notice that I am returning a pointer because C lacks & referencing available in C++, so I must work around it.
It is correct that C does not have references, but you would not need either pointer or reference if you were not using a function to wrap access to the object. I'm not really seeing what you are trying to gain by that. You would likely find it easier to get what you are looking for without. For example, when faced with duplicate external defintions of the same variable identifier, the default behavior of all but the most recent versions of GCC was to merge them into a single variable. Although current GCC reports this situation as an error, the old behavior is still available by turning on a command-line switch.
On the other hand, your inline function approach is unlikely to work in many C implementations. Note especially that inline semantics are rather different in C than in C++, and external inline functions in particular are rarely useful in C. Consider these provisions of the C standard:
paragraph 6.7.4/3 (a language constraint):
An inline definition of a function with external linkage shall not contain a definition of a modifiable object with static or thread storage duration, and shall not contain a reference to an identifier with internal linkage.
Your example code is therefore non-conforming, and conforming compilers are required to diagnose it. They may accept your code nonetheless, but they may do anything they choose with it. It seems unreasonably hopeful to expect that you could rely on a random conforming C implementation to both accept your code for the function and compile it such that callers in different translation units could obtain pointers to the same object by calling that function.
paragraph 6.9/5:
An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression [...], somewhere in the entire program there shall be exactly one external definition for the identifier [...].
Note here that although an inline definition of a function identifier with external linkage -- such as yours -- provides an external declaration of that identifier, it does not provide an external definition of it. This means that a separate external definition is required somewhere in the program (unless the function goes altogether unused). Moreover, that external definition cannot be in a translation unit that includes the inline definition. This is large among the reasons that extern inline functions are rarely useful in C.
paragraph 6.7.4/7:
For a function with external linkage, the following restrictions apply: [...] 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.
In addition to echoing part of 6.9/5, that also warns you that if you do provide an external definition of your function to go with the inline definitions, you cannot be sure which will be used to serve any particular call.
Furthermore, you cannot work around those issues by declaring the function with internal linkage, for although that would allow you to declare a static variable within, each definition of the function would be a different function. Lest there be any doubt, Footnote 140 clarifies that in that case,
Since an inline definition is distinct from the corresponding external definition and from any other corresponding inline definitions in other translation units, all corresponding objects with static storage duration are also distinct in each of the definitions.
(Emphasis added.)
So again, the approach presented in your example cannot be relied upon to work in C, though you might find that in practice, it does work with certain compilers.
If you need this to be a header-only library, then you can achieve it in a portable manner by placing an extra requirement on your users: exactly one translation unit in any program using your header library must define a special macro before including the header. For example:
/* File: sing.h */
#ifndef SING_H
#define SING_H
#ifdef SING_MASTER
int singleton = 0;
#else
extern int singleton;
#endif
#endif
With that, the one translation unit that defines SING_MASTER before including sing.h (for the first time) will provide the needed definition of singleton, whereas all other translation units will have only a declaration. Moreover, the variable will be accessible directly, without either calling a function or dereferencing a pointer.
Related
From the C18 standard:
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.
Then we read:
The declaration of an inline function with external linkage can result
in either an external definition, or a definition available for use
only within the translation unit. A file scope declaration with extern
creates an external definition.
I've written a bit of code to check if the function is actually inline or not. I've used this restriction to find out:
An inline definition of a function with external linkage shall not
contain a definition of a modifiable object with static or thread
storage duration, and shall not contain a reference to an identifier
with internal linkage.
This is the code:
static int n = 5;
void inline foo() { n = 66; }
void inline foo(); // remove 'inline' in second version
int main() {
return 0;
}
When compiling this I get a warning saying that the inline function is using a static object, which means that foo() is, effectively, an inline function, and so it provides an inline (not external) definition. However, when I remove the inline specifier from the indicated line, I don't get the warning anymore. According to the standard, it's not an inline definition, so I guess it's providing an external definition.
What the standard is not saying, or at least I cannot see it, is whether an inline function that provides an external definition stops being an inline function, or not. According to my test, it does stop being an inline function.
If I'm right in my conclusions, which I don't know, another question arises: why an extern inline function is a useless thing?
In the question you try things in the compiler to try and deduce the language rules. This is generally a bad idea, because (a) in many situations the effect of breaking the rules is hard to observe, and (b) the compiler might be bugged. Instead, the Standard is an authoritative source for what the language rules are, so the question should be answered by referring to the Standard.
Moving on: your code contains a constraint violation of C11 6.7.4/3, which you quoted in your question. The effect of a constraint violation is that the compiler must issue a diagnostic, which it did.
Then you ask about some modification, I assume you mean the following code:
static int n = 5;
void inline foo() { n = 66; }
void foo();
int main() { return 0; }
As covered by the first sentence you quoted (from 6.7.4/7), the definition of foo() is not an inline definition, because it is not true that all of the file-scope declarations in the TU include the inline specifier without extern. (That sentence is intended to deny the antecedent).
Since it is not an inline definition, there is no problem with n = 66 and the code is correct.
What the standard is not saying, or at least I cannot see it, is whether an inline function that provides an external definition stops being an inline function, or not
An inline function definition is never an external definition. This is clearly stated in 6.7.4/7 "An inline definition does not provide an external definition for the function".
Maybe your confusion arises from conflating the concepts "inline function definition" and "function definition with the inline specifier".
another question arises: why an extern inline function is a useless thing?
If you mean the keywords extern inline that is another topic that was not touched on by this question, see here. Inline functions with external linkage are certainly not useless .
I feel I need to answer myself, as this is even more complex than I expected at the beginning, and new facts have arisen during my research since I wrote the question. This is more like my own conclusions, but I feel I'm in the right path. So I need to share. Feedback and confirmation/rejection will be most appreciated.
In the first place, take a look at this code:
void inline foo() { return; }
int main() {
foo();
return 0;
}
It might seem like a simple code, but the fact is that it doesn't compile. Well, actually, it compiles, but it fails in the linker step. Why? Let's read the full difficult-to-understand paragraph from the standard:
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.
From "It is unspecified whether a call to the function uses the inline definition or the external definition" we get the answer of why it didn't compile (link) well. My implementation (GCC) chose the external version. And the linker doesn't know about such external function.
The standard says an inline definition "does not forbid an external definition in another translation unit". Actually it doesn't, but it even makes mandatory to define it elsewhere if the function is called from the present translation unit and the implementation chooses to call the external version.
Then, another question arises: if the implementation choses to call the external definition, or the inline definition, why is it necessary to define both? Well I found the answer in GCC documentation: you never know when one will be chosen or the other. For instance, GCC chooses the external version when no optimizer switches are indicated. For many optimized code configurations, inline versions will be chosen.
And regarding the question about why inline extern functions could be useless, actually they are not. External functions can also be inlined. Check this document: https://gcc.gnu.org/onlinedocs/gcc/Inline.html
An external inline function can be used and inlined from other translation units, it just doesn't create an inline definition. Inline definitions are only useful when you want to have alternative versions of a function that are used depending on optimization switches, for instance.
However, I think the standard is not very clear about the inlining of external inline functions. What GCC does, for example is: non-static inline functions are not inline functions, unless they have inline and extern specifiers in the declaration (not in the external definition) of the function.
When I try to build this code
inline void f() {}
int main()
{
f();
}
using the command line
gcc -std=c99 -o a a.c
I get a linker error (undefined reference to f). The error vanishes if I use static inline or extern inline instead of just inline, or if I compile with -O (so the function is actually inlined).
This behaviour seems to be defined in paragraph 6.7.4 (6) of the C99 standard:
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.
If I understand all this correctly, a compilation unit with a function defined inline as in the above example only compiles consistently if there is also an external function with the same name, and I never know if my own function or the external function is called.
Isn't this behaviour completely daft? Is it ever useful to define a function inline without static or extern in C99? Am I missing something?
Summary of answers
Of course I was missing something, and the behaviour isn't daft. :)
As Nemo explains, the idea is to put the definition of the function
inline void f() {}
in the header file and only a declaration
extern inline void f();
in the corresponding .c file. Only the extern declaration triggers the generation of externally visible binary code. And there is indeed no use of inline in a .c file -- it's only useful in headers.
As the rationale of the C99 committee quoted in Jonathan's answer explicates, inline is all about compiler optimisations that require the definition of a function to be visible at the site of a call. This can only be achieved by putting the definition in the header, and of course a definition in a header must not emit code every time it is seen by the compiler. But since the compiler is not forced to actually inline a function, an external definition must exist somewhere.
Actually this excellent answer also answers your question, I think:
What does extern inline do?
The idea is that "inline" can be used in a header file, and then "extern inline" in a .c file. "extern inline" is just how you instruct the compiler which object file should contain the (externally visible) generated code.
[update, to elaborate]
I do not think there is any use for "inline" (without "static" or "extern") in a .c file. But in a header file it makes sense, and it requires a corresponding "extern inline" declaration in some .c file to actually generate the stand-alone code.
From the standard (ISO/IEC 9899:1999) itself:
Appendix J.2 Undefined Behaviour
...
A function with external linkage is declared with an inline function specifier, but is not also defined in the same translation unit (6.7.4).
...
The C99 Committee wrote a Rationale, and it says:
6.7.4 Function specifiers
A new feature of C99: The inline keyword, adapted from C++, is a function-specifier that
can be used only in function declarations. It is useful for program optimizations that require the
definition of a function to be visible at the site of a call. (Note that the Standard does not attempt to specify the nature of these optimizations.)
Visibility is assured if the function has internal linkage, or if it has external linkage and the call
is in the same translation unit as the external definition. In these cases, the presence of the
inline keyword in a declaration or definition of the function has no effect beyond indicating a
preference that calls of that function should be optimized in preference to calls of other functions declared without the inline keyword.
Visibility is a problem for a call of a function with external linkage where the call is in a
different translation unit from the function’s definition. In this case, the inline keyword
allows the translation unit containing the call to also contain a local, or inline, definition of the
function.
A program can contain a translation unit with an external definition, a translation unit with an
inline definition, and a translation unit with a declaration but no definition for a function. Calls
in the latter translation unit will use the external definition as usual.
An inline definition of a function is considered to be a different definition than the external
definition. If a call to some function func with external linkage occurs where an inline
definition is visible, the behavior is the same as if the call were made to another function, say
__func, with internal linkage. A conforming program must not depend on which function is
called. This is the inline model in the Standard.
A conforming program must not rely on the implementation using the inline definition, nor may
it rely on the implementation using the external definition. The address of a function is always the address corresponding to the external definition, but when this address is used to call the
function, the inline definition might be used. Therefore, the following example might not
behave as expected.
inline const char *saddr(void)
{
static const char name[] = "saddr";
return name;
}
int compare_name(void)
{
return saddr() == saddr(); // unspecified behavior
}
Since the implementation might use the inline definition for one of the calls to saddr and use
the external definition for the other, the equality operation is not guaranteed to evaluate to 1
(true). This shows that static objects defined within the inline definition are distinct from their
corresponding object in the external definition. This motivated the constraint against even
defining a non-const object of this type.
Inlining was added to the Standard in such a way that it can be implemented with existing linker
technology, and a subset of C99 inlining is compatible with C++. This was achieved by requiring that exactly one translation unit containing the definition of an inline function be
specified as the one that provides the external definition for the function. Because that
specification consists simply of a declaration that either lacks the inline keyword, or contains
both inline and extern, it will also be accepted by a C++ translator.
Inlining in C99 does extend the C++ specification in two ways. First, if a function is declared
inline in one translation unit, it need not be declared inline in every other translation unit.
This allows, for example, a library function that is to be inlined within the library but available
only through an external definition elsewhere. The alternative of using a wrapper function for
the external function requires an additional name; and it may also adversely impact performance
if a translator does not actually do inline substitution.
Second, the requirement that all definitions of an inline function be “exactly the same” is
replaced by the requirement that the behavior of the program should not depend on whether a
call is implemented with a visible inline definition, or the external definition, of a function.
This allows an inline definition to be specialized for its use within a particular translation unit.
For example, the external definition of a library function might include some argument validation that is not needed for calls made from other functions in the same library. These
extensions do offer some advantages; and programmers who are concerned about compatibility
can simply abide by the stricter C++ rules.
Note that it is not appropriate for implementations to provide inline definitions of standard
library functions in the standard headers because this can break some legacy code that redeclares standard library functions after including their headers. The inline keyword is
intended only to provide users with a portable way to suggest inlining of functions. Because the
standard headers need not be portable, implementations have other options along the lines of:
#define abs(x) __builtin_abs(x)
or other non-portable mechanisms for inlining standard library functions.
> I get a linker error (undefined reference to f)
Works here: Linux x86-64, GCC 4.1.2. May be a bug in your compiler; I don't see anything in the cited paragraph from the standard that forbids the given program. Note the use of if rather than iff.
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.
So, if you know the behavior of the function f and you want to call it in a tight loop, you may copy-paste its definition into a module to prevent function calls; or, you may provide a definition that, for the purposes of the current module, is equivalent (but skips input validation, or whatever optimization you can imagine). The compiler writer, however, has the option of optimizing for program size instead.
I read several questions in stackoverflow about inline in C but still am not clear about it.
static inline void f(void) {} has no practical difference with static void f(void) {}.
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?
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.
A C code can be optimized in two ways: For Code size and for Execution Time.
inline functions:
gcc.gnu.org says,
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.
To sum it up:
For inline void f(void){},
inline definition is only valid in the current translation unit.
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.
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.
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:
// a declaration mentioning inline
inline int max(int a, int b);
// a definition mentioning inline
inline int max(int a, int b) {
return a > b ? a : b;
}
Here is a reference which can give you more clarity on the inline functions in C & also on the usage of inline & extern.
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.
As the word "Inline" say "In" "Line", adding this keyword to a function affects the program in runtime, when a program is compiled, the code written inside a function is pasted under the function call, as function calls are more costly than inline code, so this optimizes the code.
So, static inline void f(void) {} and static void f(void) {}, here the inline keyword does make a difference in runtime. But when the function has too many lines of code then it won't affect runtime.
If you add static before a function, the function's lifetime is the lifetime of the whole program. And that function use is restricted to that file only.
To know about extern you can refer to - Effects of the extern keyword on C functions
If I try to compile the following C code without declaring the function static, I get a linker error:
undefined reference to '_fun'
but it works if I don't make it static. In c++, it works just fine without the static keyword.
// Doesn't work
inline int fun()
{
return 3;
}
// Works
static inline int fun()
{
return 3;
}
int main(int argc, const char * argv[])
{
printf("%i", fun());
}
The requirements for inline in C are defined by section 6.7.4 of the ISO C standard. Quoting this section from the N1256
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.
As far as I can tell, your definition satisfies all those requirements. This:
inline int fun()
{
return 3;
}
is both a declaration and a definition of fun. Without the inline keyword, it would have external linkage.
The tricky part is the last sentence:
It is unspecified whether a call to the function uses the inline
definition or the external definition.
In this case, there is no external definition. You don't say what compiler you're using, but gcc -std=c99 -pedantic apparently chooses, by default, to use the external definition, and since there isn't one, you get a linker error. (Without -std=c99 -pedantic, there's no linker error, but that's because gcc also implements inline as an extension on top of C90.)
If you're only going to be using the function in that one source file, you might as well add the static keyword anyway, to give it internal linkage.
And experiment shows that your program compiles, links, and runs correctly if I compile it with optimization, using any of -O1, -O2, or -O3.
A footnote in the C standard seems to imply that gcc is behaving correctly. An example in the same section has a similar non-static inline function definition:
inline double cels(double t)
{
return (5.0 * (t - 32.0)) / 9.0;
}
followed by:
Because cels has external linkage and is referenced, an external
definition has to appear in another translation unit (see 6.9);
the inline definition and the external definition are distinct and
either may be used for the call.
The Standard's intention seems to be that if an inline function has internal linkage, it should be defined just once in the source file that uses it, but if it has external linkage, the inline definition is an alternative to a non-inline definition that must appear elsewhere. The choice of whether to call the external function or expand the inline definition is left to the whim of the compiler.
Some points not directly relevant to your question:
int fun() should probably be int fun(void). The empty parentheses are legal, but they indicate that the function takes an unspecified number and type(s) of arguments. The void specifies that it takes no arguments, which is what you want.
You need #include <stdio.h> if you're going to call printf; this is not optional.
You don't want const in the declaration of argv. For that matter, since you don't refer to the command-line arguments, you can write int main(void).
C99 inline semantics are subtle - in fact, that whole part of the language (storage duration vs linkage, tentative and inline definitions) is a mess.
While inline acts as a compiler hint in definitions that include a storage class specifier (static or extern) and can basically be ignored, the semantics change if no specifier is present.
A definition like inline int fun(void) { ... } does two things:
First, it declares an identifier with external linkage, without providing a corresponding external definition. This means such a definition must be provided by a different translation unit or we end up with undefined behaviour (probably manifesting as failure to link).
Second, it provides an inline definition, which is an alternative to the external one. As the function body is visible in the current translation unit, the compiler may use it to inline the function or for type specialization.
To get the external definition, until fairly recently, I thought it necessary to repeat the function definition in another translation unit (or fake that with 4 lines of preprocessor code).
However, that's not necessary: A single line of code - a re-declaration of the function that includes the extern specifier - is enough to make the inline definition into an external one.
In your example, this would mean putting
inline int foo(void)
{
return 42;
}
into a header file foo.h and providing a source file foo.c with contents
#include "foo.h"
// force definition to be external instead of inline
// I believe inline could be omitted, but it doesn't hurt
extern inline foo(void);
Why is this useful? As C lacks templates, generic code normally comes with a performance penalty as you need to fake generics with void* and function pointers (or, in more complex cases, vtables).
However, a sufficiently smart optimizer can get back most (potentially all) of the performance benefits of templates, but (in the absence of link-time optimization) only if the relevant function definitions are visible in the current translation unit.
While this could be achieved by putting static definitions in headers, this might increase code size to unacceptable levels in the same way that C++ templates might.
In contrast, with a C99 inline function, the compiler is free to ignore the inline definition in favour of the external one, which could even reside in a shared library.
A good example of a function that would benefit from this is qsort(), with an inline definition in stdlib.h and an external one in libc.so. There's no a priori reason for qsort() to be slower than std::sort().
IMO both make the function to have a scope of the translation unit only.
What's the difference between "static" and "static inline" function?
Why should inline be put in a header file, not in .c file?
By default, an inline definition is only valid in the current translation unit.
If the storage class is extern, the identifier has external linkage and the inline definition also provides the external definition.
If the storage class is static, the identifier has internal linkage and the inline definition is invisible in other translation units.
If the storage class is unspecified, the inline definition is only visible in the current translation unit, but the identifier still has external linkage and an external definition must be provided in a different translation unit. The compiler is free to use either the inline or the external definition if the function is called within the current translation unit.
As the compiler is free to inline (and to not inline) any function whose definition is visible in the current translation unit (and, thanks to link-time optimizations, even in different translation units, though the C standard doesn't really account for that), for most practical purposes, there's no difference between static and static inline function definitions.
The inline specifier (like the register storage class) is only a compiler hint, and the compiler is free to completely ignore it. Standards-compliant non-optimizing compilers only have to honor their side-effects, and optimizing compilers will do these optimizations with or without explicit hints.
inline and register are not useless, though, as they instruct the compiler to throw errors when the programmer writes code that would make the optimizations impossible: An external inline definition can't reference identifiers with internal linkage (as these would be unavailable in a different translation unit) or define modifiable local variables with static storage duration (as these wouldn't share state accross translation units), and you can't take addresses of register-qualified variables.
Personally, I use the convention to mark static function definitions within headers also inline, as the main reason for putting function definitions in header files is to make them inlinable.
In general, I only use static inline function and static const object definitions in addition to extern declarations within headers.
I've never written an inline function with a storage class different from static.
inline instructs the compiler to attempt to embed the function content into the calling code instead of executing an actual call.
For small functions that are called frequently that can make a big performance difference.
However, this is only a "hint", and the compiler may ignore it, and most compilers will try to "inline" even when the keyword is not used, as part of the optimizations, where its possible.
for example:
static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};
This tight loop will perform a function call on each iteration, and the function content is actually significantly less than the code the compiler needs to put to perform the call. inline will essentially instruct the compiler to convert the code above into an equivalent of:
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
Skipping the actual function call and return
Obviously this is an example to show the point, not a real piece of code.
static refers to the scope. In C it means that the function/variable can only be used within the same translation unit.
From my experience with GCC I know that static and static inline differs in a way how compiler issue warnings about unused functions. More precisely when you declare static function and it isn't used in current translation unit then compiler produce warning about unused function, but you can inhibit that warning with changing it to static inline.
Thus I tend to think that static should be used in translation units and benefit from extra check compiler does to find unused functions. And static inline should be used in header files to provide functions that can be in-lined (due to absence of external linkage) without issuing warnings.
Unfortunately I cannot find any evidence for that logic. Even from GCC documentation I wasn't able to conclude that inline inhibits unused function warnings. I'd appreciate if someone will share links to description of that.
One difference that's not at the language level but the popular implementation level: certain versions of gcc will remove unreferenced static inline functions from output by default, but will keep plain static functions even if unreferenced. I'm not sure which versions this applies to, but from a practical standpoint it means it may be a good idea to always use inline for static functions in headers.
In C, static means the function or variable you define can be only used in this file(i.e. the compile unit)
So, static inline means the inline function which can be used in this file only.
EDIT:
The compile unit should be The Translation Unit
In C++, one important effect of inline (that is not mentioned in the other answers yet, I think) is that it prevents linker errors when multiple definitions of the function are found.
Consider a function that is defined in a header file to allow it to be inlined into the source files that include the header. If the compiler decides to not inline (all calls to) this function, the function definition will be included into every object file that references it (i.e. does not inline all calls).
This might cause multiple definitions of the functions to read the linker (though not always, since it depends on the inlining decisions made by the compiler). Without the inline keyword, this produces a linker error, but the inline keyword tells the linker to just pick one definition and discard the rest (which are expected to be equal, but this is not checked).
The static keyword, on the other hand, ensures that if a function is included in the object file, it will be private to that object file. If multiple object files contain the same function, they will coexist and all calls to the function will use their "own" version. This means that more memory is taken up. In practice, I believe this means that using static for functions defined in header files is not a good idea, better to just use inline.
In practice, this also means that static functions cannot produce linker errors, so the effect of inline above is not really useful for static functions. However, as suggested by ony in another answer, adding inline might be helpful to prevent warnings for unused functions.
Note that the above is true for C++. In C, inline works a bit different, and you have to explicitly put an extern declaration in a single source file to have the inline function emitted into that object file so it is available for any non-inlined uses. In other words, inline means that a function is not emitted into any source file, even when not all calls are inlined, unless it is also specified as extern, and then it is emitted (even if all local calls are inlined). I'm not sure how that interacts with static, though.
An inline definition is not externally linked.
// average.h
#ifndef AVERAGE_H
#define AVERAGE_H
inline double average(double a, double b);
#endif
Attempting to call an inline function with the definition above from another
module after it has been preprocessed or linked to a c file will result in an error.
There are two ways to solve this problem:
make it a static inline function defintion.
Example:
// average.h
#ifndef AVERAGE_H
#define AVERAGE_H
static inline double average(double a, double b);
#endif
include the defintion from the c file and make it external.
Example:
#include "average.h"
extern double average(double a ,double b){
return (a + b) / 2;
}