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

193,998

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.

Share:
193,998

Related videos on Youtube

new_perl
Author by

new_perl

Updated on July 19, 2020

Comments

  • new_perl
    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?

  • new_perl
    new_perl over 12 years
    Apart from the embedding feature,it's the same as static,right?
  • K-ballo
    K-ballo over 12 years
    Or in fancy words: it has internal linkage.
  • littleadv
    littleadv over 12 years
    No, static refers to the scope. In C it means that the function/variable can only be used within the same translation unit.
  • new_perl
    new_perl over 12 years
    What about using inline in definition? Do you also imply not using it for extern functions?
  • VoidStar
    VoidStar over 12 years
    It'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
    littleadv over 12 years
    @VoidStar Actually static (with or without inline) can be in header perfectly well, see no reason why not. Templates is for C++, this question is about C.
  • Christoph
    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
    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
    shengy over 10 years
    I believe the compile unit is something I wrote in error, there is no such thing, the actual terminology is translation unit
  • Z boson
    Z boson over 8 years
    Is 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
    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-unreferenced static functions and data.
  • syockit
    syockit over 7 years
    Have 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 specifying inline still inlines it, so there is no difference between static and static inline.
  • Ruslan
    Ruslan over 6 years
    Actually 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
    Tyg13 over 5 years
    This 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
    John Z. Li over 4 years
    upvoted for "use the convention to mark static function definitions in headers inline".
  • jaques-sam
    jaques-sam about 4 years
    Mmm, still got warning: unused function 'function' [clang-diagnostic-unused-function] for a static 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 combining static & inline!
  • jaques-sam
    jaques-sam about 4 years
    Your answer is not complete because it's mostly used in header files, accross translation units.
  • user541686
    user541686 almost 4 years
    I read your entire answer and I still don't get the semantic difference between static and static inline. Both of them make the definition invisible to other translation units. So what would be a sensible reason to write static inline instead of static?
  • mtraceur
    mtraceur almost 4 years
    @Ruslan No, static already does all that, and predates inline. inline was added after, as a way to explicitly suggest that the intended or optimal thing is for the function to be inlined.
  • mtraceur
    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 before inline was added to the language.
  • mtraceur
    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
    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, whereas static 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, and inline is the most "native" way to say so in the language of C.
  • mtraceur
    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, and static 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
    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 with static) in every translation unit even in cases where the function is never inlined. All the cases static, inline and static inline are distinct in their semantics.
  • mtraceur
    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 (which static also does), and 2. inline as a side-effect empowers the compiler to inline the function (which static 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
    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 a static 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 of extern functions to be included in multiple translation without violating the ODR, and this in turn empowers the compiler to inline them.
  • Ruslan
    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
    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
    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 after static? But from the answer itself, I gathered that the compiler meaning is: "emit an error if this extern inline function tries to use a static variable." But this isn't the case with a static inline function, so I also don't understand the difference between static inline and static INLINE_INTENT where INLINE_INTENT is an empty #define.
  • SO_fix_the_vote_sorting_bug
    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
    SO_fix_the_vote_sorting_bug about 3 years
    major versions of gcc from 4.1 all the way to 11.1 will remove unused static and unused static inline functions over at godbolt.org. And they all warn about unused for static functions, but none warn for unused static 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 just inline.)
  • mtraceur
    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 and static 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
    Etienne M over 2 years
    Clang llvm uses a different threshold for inline specified functions: godbolt.org/z/rar9adfbv I dare say clang trunk is a "modern compiler"