24

What happens if I define the function in my .h file as

extern int returnaint(void);

define it in the related .c file as

inline int returnaint(void) {
    return 1;
}

and include the header in another .c file and use the function? When I compile the things seperatly, creating a object file for each .c file and then link them, is the inlined function included, or what happens?

I know the compiler can ignore inline, but what if it does not ignore it in this case?

Cardinal System
  • 2,749
  • 3
  • 21
  • 42
musicmatze
  • 4,124
  • 7
  • 33
  • 48
  • 2
    Then you get a linker error. –  Jul 06 '13 at 15:33
  • 2
    @H2CO3, no there will never be a linker error. The compilation unit with the `inline` definition also see an `extern` declaration, so a symbol must be emitted. Please see my answer. – Jens Gustedt Jul 06 '13 at 18:29
  • 2
    Note that the semantics of inline are only defined since c99 and some compilers (e.g. gcc) still default to c89. http://www.greenend.org.uk/rjk/tech/inline.html has a nice summary and a guide on how to use inline depending on the compiler standards you want to support. – Uwe Kleine-König Sep 26 '14 at 15:12
  • 1
    Possible duplicate of [extern inline](http://stackoverflow.com/questions/216510/extern-inline). Also see [What's the difference between static inline, extern inline and a normal inline function?](http://stackoverflow.com/q/216510) and Jonathan Wakely's answer on the GCC mailing list at [undefined errors for inline function](http://gcc.gnu.org/ml/gcc-help/2017-01/msg00114.html). – jww Jan 30 '17 at 10:53

2 Answers2

39

Having added the inline to the function definition in the .c file is just superfluous.

  • Your compilation unit of the .c file sees an extern declaration (without inline) and an inline definition. Thus it emits the symbol for the function in the object file.

  • All other compilation units only see an extern declaration, and so they can use the function without problems, if you link your final executable with the other .o file.

In fact, you just have it the wrong way around. This feature is meant to be used that you have the inline defintion in the .h file, visible to everybody. This definition of the function only acts as a declaration of the symbol, just as extern would, but doesn't define it.

An extern declaration in just one .c file (compilation unit) then ensures such that the symbol is defined, there.

The terminology is a bit confusing, the inline definition acting as declaration of the symbol, and the extern declaration acting as definition of it

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • 2
    Nice point. I think I should move my inline functions to the header! :-) – musicmatze Jul 13 '13 at 09:17
  • 1
    Adding inline in the translation unit that defines the function has an effect. The probable result is that usages of said function in this compilation unit will be inlined. – Uwe Kleine-König Sep 26 '14 at 15:09
  • 1
    @UweKleine-König, no. The compiler is free to do whatever pleases. If the definition of the function is visible, the compiler may or may not chose to inline, as long as it obeys the "as-if" rule. Nothing changes by adding `inline` to that definition. – Jens Gustedt Sep 26 '14 at 21:39
  • 1
    @JensGustedt, that doesn't contradict my statement. Yes, "inline" is only a hint to the compiler. But assuming adding that hint makes a difference in practice, exactly that difference applies to the usages of the respective function in the same compilation unit. – Uwe Kleine-König Oct 06 '14 at 09:16
  • 3
    The compilers that I use, mainly gcc but also clang or icc, don't make a difference with `inline`, they don't even take it as a hint. To convince them that you know better than them, you'd have to use some compilation flags or use `__attribute__((allways_inline))` to make a difference. So no, don't expect that just adding `inline` changes anything. – Jens Gustedt Oct 06 '14 at 09:57
  • Your last statement is false (Or at least, wrong). An `inline` definition in a header file **does** declare an external symbol, however, it does not **define** it. Therefore, you need to **define** the function `extern` in a `.c` file, not **declare** it, as an undefined symbol is undefined behaviour, though, in practice, the compiler doesn't care if your inline function is not defined externally, as long as it doesn't need it. – yyny Sep 23 '16 at 11:48
  • An `inline` definition has the same meaning as an `extern` declaration, except for that makes the definition `inline`, i.e. you can define something `inline` even it is already defined (This usually means that the function is inlined, or at least has it's symbol changed) – yyny Sep 23 '16 at 11:50
  • Though I guess implied that the `.c` file includes the `.h` file, in which case the `extern` declaration makes the `inline` definition `extern inline`. – yyny Sep 23 '16 at 11:56
  • 1
    @YoYoYonnY, the vocabulary is not easy to get right. Perhaps with my edit it works better, now? – Jens Gustedt Sep 23 '16 at 11:58
  • @JensGustedt Good edit, though what I was trying to convay is that the function _needs_ to be **defined** `extern`, therefore, I think something along the lines of "..., the `inline` **definition** declaring the symbol, and the `extern` **declaration** making that `inline` definition **define** the symbol" might help, thought this also makes the explanation itself more confusing. Alternatively, you could just explain that an `inline` definition needs an `extern` definition too, and that declaring an `inline` definition `extern` does exactly this. – yyny Sep 23 '16 at 12:13
  • [cont] Basically, `extern void f(void); inline void f(void) {};` is equal `extern inline f(void) {}`, which is equal `extern f(void) {}` for all other translation units. – yyny Sep 23 '16 at 12:16
  • `inline` defintion in the .h file is defined for each translation unit's own internal definition. I mean that it is also definition. But it is actually used as definition only when a translation unit treats its inline function call statement as function inlining, not function call. – rosshjb Jan 25 '21 at 15:16
  • If anything starting from "In fact, you just have it the wrong way around." (especially the last paragraph) is confusing to you, https://stackoverflow.com/a/216546/571168, https://stackoverflow.com/a/6312813/571168, and https://stackoverflow.com/a/6312854/571168, and the summary in https://stackoverflow.com/q/6312597/571168 might help. – Daniel Le Nov 07 '21 at 10:59
4

It won't compile. From C11 (ISO/IEC 9899:2011) §6.7.4 Function specifiers (emphasis added):

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.

The other .c file gets only the declaration of the inline function from the header, but not the definition, so it's against the rule in bold font.

EDIT:

As @Jens Gustedt points out, my previous explanation is wrong, because in the OP's question, the function is declared as non-inline in the header file:

extern int returnaint(void);

So the other .c file will treat it like a normal function.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • 14
    wrong answer. the other `.c` files don't see `inline` the declaration in the `.h` only has `extern` not `inline`. – Jens Gustedt Jul 06 '13 at 18:30