I am trying to understand extern inline and inline functions.
What's the difference between static inline, extern inline and a normal inline function?
Quoting lines from the above link: "A function definition with just inline defines an inline function with external linkage. However, such definition is referred to as inline definition and it does not work as external definition for that function. That means that even though this function has external linkage, it will be seen as undefined from other translation units, unless you provide a separate external definition for it somewhere.
A function definition with extern inline defines an inline function with external linkage and at the same time this definition serves as external definition for this function. It is possible to call such function from other translation units."
But I am not able to understand this correctly.
I have a sample code which explains what I understood:
In temp1.c
#include <stdint.h>
extern int32_t fun1(void);
int32_t main(void)
{
int32_t result = fun1();
return result;
}
In temp2.c
#include <stdint.h>
int32_t fun1(void);
inline int32_t fun1(void)
{
return 0;
}
Since fun1 is a inline definition in temp2.c, it will be seen as undefined from temp1.c. So external declaration in temp1.c made temp1.c to access fun1 from temp2.c. I am confused as in the quotes it is saying "separate external definition" instead of external declaration.
temp1.c
#include <stdint.h>
int32_t fun1(void);
int32_t main(void)
{
int32_t result = fun1();
return result;
}
temp2.c
#include <stdint.h>
extern inline int32_t fun1(void)
{
return 0;
}
Since fun1 is extern inline function, it can be called from temp1.c. The only difference what I observed is, no need of explicit declaration of the extern inline function where it is defined.
Is it the only difference ? else what are the other major difference and the scope of inline and extern inline functions ?
Please correct if any of the above observation is wrong
With respect to the first, "inline function" example, you say (highlighting added to function names),
Since
fun1
is a inline definition in temp2.c, it will be seen as undefined from temp1.c. So external declaration in temp1.c made temp1.c to accessfun1
from temp2.c.
Your explanation is incorrect, or at least misworded. In this example, your temp2.c does not provide an external definition of function . Function fun1()
. The declaration in temp1.c says that there is an external definition somewhere, but temp2.c is not that place. There needs to be an external definition provided by some other translation unitfun1
in temp2.c is an inline function because it is declared with the inline
keyword (that's all it means to be an "inline function"), but the definition of fun1
in that file is not an inline definition, because temp2.c contains another declaration of its identifier that does not include the inline
keyword. Since fun1
is declared with (implicitly) external linkage, that is an external definition of fun1
. Anyone can call it. To get an inline definition of a function, every declaration of its identifier in the TU must include the inline
keyword and must omit the extern
keyword.
Standard C does require the function to be declared in temp1.c if it is to be called from that TU, but nothing you put in that file could enable code within to access an inline definition of fun1
from a different TU. Only external definitions are accessible across TUs -- that's what being an external definition means.
Note: The original (now stricken-out) text of this part of this answer supposed that temp2.c indeed did provide an inline definition of function fun1
, because I overlooked the flaw(?) in the declarations.
I am confused as in the quotes it is saying "separate external definition" instead of external declaration.
A function definition comprises a declaration of that function, but not every function declaration is part of a definition. We must be careful with our wording here. There is no meaningful sense of an "external function declaration" in C, in that no declaration has a scope wider than its translation unit.
But one can, and often does, have (local) declarations of functions with external linkage. This is the default, applicable to all function declarations that do not include the keyword static
. That default can be made explicit by use of the extern
keyword, and that happens to have additional significance for declarations of inline functions.
An external function definition, on the other hand, is one that can be accessed by name from another translation unit. An inline definition explicitly is not an external definition. Thus, your first example declares that there is a function fun1
with external linkage, but does not if all the declarations of that identifier carried the inline
keyword and not extern
then it would not provide a corresponding external definition of that function. If that function is were called, even from a source file that provides an inline definition, then the absence of an external definition is would be an error.
With respect to the second, "extern inline function" example, you say (highlighting added to function names),
Since
fun1
is extern inline function, it can be called from temp1.c.
Let's separate out the properties here.
fun1
is (still) declared as a function with external linkage.inline
specifier in the declaration that is part of its definition makes it an inline function.extern
specifier on a declaration of that function in the same translation unit as a definition makes the definition in that TU an external one.It is the fact that the definition in temp2.c is an external one that makes it callable from temp1.c.
The only difference what I observed is, no need of explicit declaration of the extern inline function where it is defined.
There is no need for a forward declaration of fun1()
in the first example, either. There would be a need for a forward declaration in both cases if temp2.c contained a call to fun1
prior to that function's definition. There is no difference here.
Update:
You are more or less right. Your two alternatives are different ways to declare an an inline function with external linkage and to provide an external definition for it. Instead, the thing you should be comparing to, and to which the original text of this answer was erroneously addressed, would be this:
#include <stdint.h>
inline int32_t fun1(void);
inline int32_t fun1(void)
{
return 0;
}
or, equivalently, this:
#include <stdint.h>
inline int32_t fun1(void)
{
return 0;
}
In those cases, the provided definition of fun1
is an inline definition, accessible only from the translation unit of temp2.c. Of course, that's not useful unless there is code in that TU that actually calls the function.
Is it the only difference ? else what are the other major difference and the scope of inline and extern inline functions ?
You are doing yourself a disservice by attempting to set up "inline" and "extern inline" as classes of functions. There are inline functions and non-inline functions. There are function identifiers with internal linkage and those with external linkage. There are inline function definitions, internal ones, and external ones, and appearance of a function declaration in a TU does not necessarily require a definition in the same TU. These combinations (and only these) of those properties are possible:
A function identifier declared with external linkage in a given TU refers refers to an external function definition, which may appear in a different TU.
A function identifier declared with internal linkage in a given TU refers refers to an internal or inline function definition in the same TU.
An inline function declaration may have either external or internal linkage, in either case, an inline definition of that function must appear in the same TU. If the function identifier has external linkage (in that TU) and an inline function definition then it is left to the discretion of the implementation whether and where the inline definition or the (required) external definition elsewhere is used within that TU.
Update:
Upon reflection, your characterization of functions themselves as "inline functions" and "extern inline functions" seems to reflect the idea that inline character of a function is globally associated with the function's identifier (e.g. fun1
), at least for identifiers with external linkage. This is not the case, as I hope my rather lengthy discourse has conveyed.
Inline character of a function identifier is a per-TU property, and inline character of a function definition is a separate, per-definition property. If in any TU you declare a given function to be an inline function, then you must provide a definition of that function in that TU. An external definition of a function from a different TU does not satisfy that requirement, even if the function is declared to be an inline function in the TU in which the definition appears.