4

Here inline is used in both definition and declaration which compiles successfully:

#include <stdio.h>

inline int add(int a , int b);

inline int add(int a , int b){
 return a+b;
}

int main(){
 printf("%d\n", add(1,2));

 return 0;
}

It also compiles fine if we use inline in either definition OR declaration.

Which one is the correct way of doing it? is there a rule in C to explain it as there are similar rules for static and extern?

Josh
  • 67
  • 2
  • Not fully, still want to know why other methods are compiling and running. – Josh Jun 15 '20 at 13:28
  • @Josh: why wouldn't they compile? A non-static inline function will still be visible to other compilation units (if they choose to include the declaration) and usually won't be inlined in other units, unless compiler is configured to do link-time optimizations. If you want an inline function which has to be inlined in many compilation units, make it `static inline` and place it into a header file. – vgru Jun 15 '20 at 13:48
  • Usually, a declaration is not needed (i.e. a definition will suffice). – Fiddling Bits Jun 15 '20 at 13:50
  • Take a look at this on how `static` keyword is used: https://stackoverflow.com/questions/62379166/using-static-keyword-in-definition-vs-declaration-in-c. I'm looking for the same kind of rules in C for `inline`. – Josh Jun 15 '20 at 13:51

2 Answers2

2

even the inline needs a body. So if you only

inline int add(int a , int b);

you just inform the compiler that there is a function called add taking two ints as the parameters and returning int. You give the compiler a hint that you would like this function to be inlined.

but what will actually happen depends on the implementation.

gcc will only link the program successfully if optimizations are enabled. If not compiler will not emit the not inlined version of the function and the linking will fail. https://godbolt.org/z/yQj3jC

To make sure that it will link in any circumstances you need to:

int add(int a , int b);

inline int add(int a , int b){
 return a+b;
}

In this case yuo will have not inlined version of the function but compiler will inline it if it finds it necessary https://godbolt.org/z/2BDA7J

In this trivial example function will be inlined when optimizations are enabled even if there is no inline keyword. https://godbolt.org/z/h3WALP

inline is just the hint and compiler may choose to inline it or not. Some compilers have special mechanisms to force inlining

inline __attribute__((always_inline)) int add(int a , int b){
 return a+b;
}
0___________
  • 60,014
  • 4
  • 34
  • 74
  • Interesting, I thought if declaration is `inline`, then compiler automatically will assume any implementation is also should be `inlined`. – Josh Jun 15 '20 at 14:14
  • It gets trickier when multiple translation units are involved. 6.7.4 p10 says "An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit." – Ian Abbott Jun 15 '20 at 14:31
  • @IanAbbott Yes but it far beyond the level of the question. There was a copy-paste mistake as well. – 0___________ Jun 15 '20 at 14:53
  • @P__J__ Yes, it is easy to get confused. Indeed, I was confused by "An inline definition" because that only exists when there is no external declaration of the function in file scope. So an `inline` function definition will also be the externally linked definition of the function if it has an external declaration at file scope. In that case, the `inline` may still act as a hint to the compiler, and the function still has certain restrictions. – Ian Abbott Jun 15 '20 at 15:13
  • So the correct way is to always add the keyword at the definition and not the declaration? – user129393192 Jul 20 '23 at 15:11
  • Is this the case with `static`? Do I need to put `static` in the declaration as well, or will the definition suffice? – trxgnyp1 Aug 30 '23 at 15:10
0

Different combinations of extern and inline and no function specifiers may be valid and will compile, yet the behaviour may be different.

Whether a function will actually be inlined is defined by these two paragraphs of the C99-standard (cf, for example, this online C99 standard draft):

6.7.4 Function specifiers

...

(6) A function declared with an inline function specifier is an inline function. Making a function an inline function suggests that calls to the function be as fast as possible.138) The extent to which such suggestions are effective is implementation-defined.139)

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

Paragraph (6) defines that - even if a function is an "inline function" - it is implementation defined whether it is actually "inlined" or not.

Paragraph (7) says that only if all the declarations of a file-scope function identifier are marked as inline and none of them is marked as external, then the function is defined inline.

In your example, since you do not use an external keyword, the function will be defined as inline. If it is actually inlined is, according to paragraph (6), still implementation defined.

Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
  • Interestingly, GCC does not seem to require an explicit `extern` keyword to turn an inline defined function into an externally linked one. So adding `int add(int, int);` to the code behaves the same as adding `extern int add(int, int);` to the code. In either case, GCC produces an externally linked `add` function (that can be called from other translation units). I wonder if that's a bug in GCC. – Ian Abbott Jun 15 '20 at 15:27