Inline function which returns a variable - c

I have the following structure:
test.h:
extern BOOL some_variable;
inline BOOL get_some_variable()
{
return some_variable;
}
test.c
BOOL some_variable = 10;
// some functions that change 'some_variable'.
main.c
int main()
{
while(1) {
if (get_some_variable()) { // do something }
}
}
My question is, will this work as expected. By that I mean will call in main get replaced by 'some_variable'? Or will this create copies of 'some_variable' or something like that? Does the inlined function need to be declared extern somewhere?
I am aware I could just be checking 'some_variable' in main.c without the need of a function, but this way seems more elegant to me. Or is there a better way, to have a variable in other source file returned without calling a function. I want this to reduce the number of operations needed to get 'some_variable' because this is for a microcontroller.

I've come to agree with #JonathanLeffler's conclusion that the form of inline function definition you present requires an external definition somewhere of function get_some_variable(), which is not provided by your test.h. It may turn out that your compiler still builds your program successfully, however, as it may well choose everywhere to use the provided inline function instead of the falsely promised external one.
Nevertheless, what you're doing seems a bit silly. The whole point of an inline definition of a function with external linkage is to provide an optional local alternative to the external function. If you want the inline function to be used always, then it would be appropriate to declare it static in test.h:
extern BOOL some_variable;
static inline BOOL get_some_variable()
{
return some_variable;
}
One normally wants to avoid static declarations in headers, because they get duplicated in every translation unit that includes the header, but that's exactly what you want in a case such as this.
Or on the third hand, in this particular case you could consider just accessing the variable directly, which can be done from every translation unit anyway. If you're looking to encapsulate some_variable and restrict access to it, then you need a different approach.

Yes, I believe the function should be declared extern somewhere, strictly, though if the function is actually inlined everywhere, you won't notice the absence of an extern definition. The standard says:
6.7.4 Function specifiers
¶7 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.140)
140) 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.
As long as main.c has #include <test.h>, then you are likely to end up with the body of the function used inline — without function call overhead — in the main() program.
On the whole, it is probably safest to use static inline everywhere (as John Bollinger suggests). See also Is inline without static or extern ever useful in C, and there may well be other relevant questions on SO.

Related

Is an external linkage inline function really inline?

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.

Why does inline void foo() { ... } in a common header just work?

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

Why is static keyword required for inline function?

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

C inline functions and "undefined external" error

I'm trying to replace some macro subroutines with inline functions, so the compiler can optimize them, so the debugger can step into them, etc. If I define them as normal functions it works:
void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
but if I define them as inline:
inline void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
it says "Error: Undefined external". What does that mean? Taking a stab in the dark, I tried
static inline void do_something(void)
{
blah;
}
void main(void)
{
do_something();
}
and no more errors. The function definition and call to the function are in the same .c file.
Can someone explain why one works and the other doesn't?
(Second related question: Where do I put inline functions if I want to use them in more than one .c file?)
First, the compiler does not always inline functions marked as inline; eg if you turn all optimizations off it will probably not inline them.
When you define an inline function
inline void do_something(void)
{
blah
}
and use that function, even in the same file, the call to that function is resolved by the linker not the compiler, because it is implicitely "extern". But this definition alone does not provide an external definition of the function.
If you include a declaration without inline
void do_something(void);
in a C file which can see the inline definition, the compiler will provide an external definition of the function, and the error should go away.
The reason static inline works is that it makes the function visible only within that compilatioin unit, and so allows the compiler to resolve the call to the function (and optimize it) and emit the code for the function within that compilation unit. The linker then doesn't have to resolve it, so there is no need for an external definition.
The best place to put inline function is in a header file, and declare them static inline. This removes any need for an external definition, so it resolves the linker problem. However, this causes the compiler to emit the code for the function in every compilation unit that uses it, so could result in code bloat. But since the function is inline, it is probably small anyway, so this usually isn't a problem.
The other option is to define it as extern inline in the header, and in one C file provide and extern declaration without the inline modifier.
The gcc manual explains it thus:
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. You can
also direct GCC to try to integrate all "simple enough" functions into
their callers with the option -finline-functions.
GCC implements three different semantics of declaring a function
inline. One is available with -std=gnu89 or -fgnu89-inline or
when gnu_inline attribute is present on all inline declarations,
another when -std=c99, -std=c1x, -std=gnu99 or -std=gnu1x
(without -fgnu89-inline), and the third is used when compiling C++.
To declare a function inline, use the inline keyword in its
declaration, like this:
static inline int
inc (int *a)
{
return (*a)++;
}
If you are writing a header file to be included in ISO C90 programs,
write __inline__ instead of inline.
The three types of inlining behave similarly in two important cases:
when the inline keyword is used on a static function, like the
example above, and when a function is first declared without using the
inline keyword and then is defined with inline, like this:
extern int inc (int *a);
inline int
inc (int *a)
{
return (*a)++;
}
In both of these common cases, the program behaves the same as if you
had not used the inline keyword, except for its speed.
When a function is both inline and static, if all calls to the
function are integrated into the caller, and the function's address is
never used, then the function's own assembler code is never
referenced. In this case, GCC does not actually output assembler code
for the function, unless you specify the option
-fkeep-inline-functions. Some calls cannot be integrated for various
reasons (in particular, calls that precede the function's definition
cannot be integrated, and neither can recursive calls within the
definition). If there is a nonintegrated call, then the function is
compiled to assembler code as usual. The function must also be
compiled as usual if the program refers to its address, because that
can't be inlined.
Note that certain usages in a function definition can make it
unsuitable for inline substitution. Among these usages are: use of
varargs, use of alloca, use of variable sized data types , use of computed goto,
use of nonlocal goto, and nested functions.
Using -Winline will warn when a function marked inline could not
be substituted, and will give the reason for the failure.
As required by ISO C++, GCC considers member functions defined within
the body of a class to be marked inline even if they are not
explicitly declared with the inline keyword. You can override this
with -fno-default-inline.
GCC does not inline any functions when not optimizing unless you
specify the always_inline attribute for the function, like this:
/* Prototype. */
inline void foo (const char) __attribute__((always_inline));
The remainder of this section is specific to GNU C90 inlining.
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.
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 will cause most calls to the function to be inlined.
If any uses of the function remain, they will refer to the single copy
in the library.
For inline functions to work with C99 (they only came there into the language) you'd have to give the definition in a header file
inline void do_something(void)
{
blah
}
and in one compilation unit (aka .c) you place some sort of "instantiation"
void do_something(void);
without the inline.
You have to put them in a header file if you want to use them from multiple files.
And for the linker error: the default declaration of a function implies that it's "extern", but since it's inlined, the linker can find the compiler-generated symbol stub, hence the error.

What's the difference between "static" and "static inline" function?

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;
}

Resources