What's the difference between "static" and "static inline" function?
Solution 1
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
.
Solution 2
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.
Solution 3
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.
Solution 4
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
Solution 5
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.
Related videos on Youtube
new_perl
Updated on July 19, 2020Comments
-
new_perl almost 4 years
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?-
m7913d over 2 yearsRelated question: static vs inline for functions implemented in header files
-
-
new_perl over 12 yearsApart from the embedding feature,it's the same as
static
,right? -
K-ballo over 12 yearsOr in fancy words: it has internal linkage.
-
littleadv over 12 yearsNo,
static
refers to the scope. In C it means that the function/variable can only be used within the same translation unit. -
new_perl over 12 yearsWhat about using
inline
in definition? Do you also imply not using it forextern
functions? -
VoidStar over 12 yearsIt's also important to note that code declared as inline belongs in the header, where as normal (non-template) source code cannot go in headers without causing multiple redefinition errors. So even when declaring something inline, even if the compiler chooses not to inline it, there is still a standard-mandated multiple-redefinition avoiding behavior that kicks in.
-
littleadv over 12 years@VoidStar Actually
static
(with or withoutinline
) can be in header perfectly well, see no reason why not. Templates is for C++, this question is about C. -
Christoph over 12 years@littleadv: the main reason for putting function definitions in header files is to make them inlinable, so marking them explicitly
inline
is good style, imo -
legends2k over 10 years@AlokSave: Is there a difference between compilation unit and translation unit? If so, which is more appropriate in the context of the C++ language?
-
shengy over 10 yearsI believe
the compile unit
is something I wrote in error, there is no such thing, the actual terminology istranslation unit
-
Z boson over 8 yearsIs this still true with recent version of GCC? Your answer would be a lot more interesting if you an example and listed the which version of GCC do it.
-
R.. GitHub STOP HELPING ICE over 8 years@Zboson: I don't have that information readily available and don't have time to setup and test lots of gcc versions at the moment, but I agree it would be useful information to have. You could probably find when gcc first started optimizing out unused static functions/objects by looking at the history of
attribute((used))
and its use to allow asm to reference otherwise-unreferencedstatic
functions and data. -
syockit over 7 yearsHave you actually tried compiling your example into assembly? At least when I tried it with GCC 4.9, with no
-O
flag, or if-O0
is specified, the function call is still there. If you compile it with-O1
or above, now it is actually inlined, but even not specifyinginline
still inlines it, so there is no difference betweenstatic
andstatic inline
. -
Ruslan over 6 yearsActually
inline
doesn't instruct the compiler to do any attempts at inlining. It merely lets the programmer to include function body in multiple translation units without ODR violation. A side effect of this is that it's makes it possible for the compiler, when it would inline the function, to actually do this. -
Tyg13 over 5 yearsThis is the correct answer. Any answer talking about
inline
as if it actually applied to inlining is misleading and arguably incorrect. No modern compiler uses it as a hint to inline or require it in order to enabling inlining of a function. -
John Z. Li over 4 yearsupvoted for "use the convention to mark static function definitions in headers inline".
-
jaques-sam about 4 yearsMmm, still got
warning: unused function 'function' [clang-diagnostic-unused-function]
for astatic inline
function when building withclang-tidy
(v8.0.1), which is used in another translation unit. But definitely, this is one of the best explanations and reason for combiningstatic
&inline
! -
jaques-sam about 4 yearsYour answer is not complete because it's mostly used in header files, accross translation units.
-
user541686 almost 4 yearsI read your entire answer and I still don't get the semantic difference between
static
andstatic inline
. Both of them make the definition invisible to other translation units. So what would be a sensible reason to writestatic inline
instead ofstatic
? -
mtraceur almost 4 years@Ruslan No,
static
already does all that, and predatesinline
.inline
was added after, as a way to explicitly suggest that the intended or optimal thing is for the function to be inlined. -
mtraceur almost 4 years@Ruslan You are right that it is not instructing the compiler to attempt inlining. It is merely suggesting to the compiler to do so. But everything else you said after that was already done by
static
beforeinline
was added to the language. -
mtraceur almost 4 years+1 for the hugely insightful reminder that they are not useless, because they instruct the compiler to treat impossibility to do those optimizations as an error!
-
mtraceur almost 4 years@user541686 The biggest and most important semantic difference is that
static inline
expresses your intent/approval for it to be inlined, whereasstatic
does not. To be clear about definitions, "semantics" is basically a fancy word for "meaning", and so that is the most essential semantic difference right there. Because source code is first and foremost about describing what you intend for the code to do. And if you proactively intend for inlining to happen, you should say so, andinline
is the most "native" way to say so in the language of C. -
mtraceur almost 4 years@user541686 That said, I think there is an important thinking difference between "I intend for this to be inlined" and "I intend to empower the compiler (or the person invoking the compiler) to decide whether or not inlining is optimal in this case". Personally, I would only use
static inline
when I explicitly thought it was better for the function to be inlined, andstatic
in any other situation. And I only very, very rarely actually want to assert that it is better for something to be inlined - because that seems very situational (very implementation-dependent and usecase-dependent). -
Ruslan almost 4 years@mtraceur
inline
non-static
lets the compiler make the function accessible from other translation units instead of creating it (as it would withstatic
) in every translation unit even in cases where the function is never inlined. All the casesstatic
,inline
andstatic inline
are distinct in their semantics. -
mtraceur almost 4 years@Ruslan Okay, I see what you mean now. But to me your original comment does not seem to clearly draw that distinction. When I read that earlier comment, all I get out of it is: 1.
inline
allows including the definition of the function in multiple translation units without an ODR violation (whichstatic
also does), and 2.inline
as a side-effect empowers the compiler to inline the function (whichstatic
also does). The distinction between whether or not there is a copy in each translation unit does not seem to be mentioned, so I wasn't rejecting that. -
mtraceur almost 4 years@Ruslan Also, a
static
function which is never used in a translation unit can simply be omitted entirely by the compiler when generating the code for that translation unit, and if all uses of astatic
function are inlined by a compiler, it is similarly free to not generate an independent copy. It seems your original comment was written with non-static
functions in mind, and I totally agree with it if so, because yeah,inline
allows bodies ofextern
functions to be included in multiple translation without violating the ODR, and this in turn empowers the compiler to inline them. -
Ruslan almost 4 years@mtraceur you seem to be trying to read into my two-year-old comment as if it were an answer. It isn't, so it can't be edited, thus I don't think it's useful to try to spend such an effort to critique it.
-
mtraceur almost 4 years@Ruslan it was useful to me, because it helped me actually understand what you meant and to discover an angle of thinking from which the wording you used in it would have been naturally the wording I might have used too. Your initial comment brought up a good point that elaborates on the answer, but in a wording that meant something else to me - I think these follow-up comments will help clarify that point for other readers like myself.
-
SO_fix_the_vote_sorting_bug about 3 years@mtraceur, I think user541686 was wanting to know the practical/compiler meaning, not the programmer intent. If intent was the only deciding factor then couldn't I just
#define I_INTEND_FOR_THIS_TO_BE_INLINED
to be a nop, and place it afterstatic
? But from the answer itself, I gathered that the compiler meaning is: "emit an error if thisextern inline
function tries to use astatic
variable." But this isn't the case with astatic inline
function, so I also don't understand the difference betweenstatic inline
andstatic INLINE_INTENT
whereINLINE_INTENT
is an empty#define
. -
SO_fix_the_vote_sorting_bug about 3 years@DrumM, but ony was referring to gcc. But you're right, this is probably the best explanation so far.
-
SO_fix_the_vote_sorting_bug about 3 yearsmajor versions of gcc from 4.1 all the way to 11.1 will remove unused
static
and unusedstatic inline
functions over at godbolt.org. And they all warn about unused forstatic
functions, but none warn for unusedstatic inline
. Also, unspecified storage class functions will remain if unused, without warning (even with optimizations). But I don't know how to test with headers on that site. (And I would get linker errors on anything above gcc 4.9.x when trying to compile with justinline
.) -
mtraceur about 3 years@jdk1-0 Intent is ideally communicated to both humans and software. Humans first and foremost, but the compiler and other tools can do a better job at optimizing or detecting problems if you can tell them your intent. So in the intent perspective, the difference between
static inline
andstatic INLINE_INTENT
is that one of them also reveals your intent to compilers and other software (because we standardized on that as the way to express that specific intent). -
Etienne M over 2 yearsClang llvm uses a different threshold for inline specified functions: godbolt.org/z/rar9adfbv I dare say clang trunk is a "modern compiler"