11

I tried to search a good answer online but fail to get one I can fully understand. Suppose I have a header "add.h":

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

A file called "adddouble.c":

#include "add.h"

int adddouble(int a, int b){ return 2*add(a,b); }

A file called "addsquare.c":

#include "add.h"

int addsquare(int a, int b){ return add(a,b)*add(a,b); }

A main file "main.c":

#include<stdio.h>

int adddouble(int, int);
int addsquare(int, int);
int main(){
printf("add double = %d\n", adddouble(10,20));
printf("add square = %d\n", addsquare(10,20));
return 0;
}

I use gcc5.2.0 to compile those files, but got: "Undefined symbols for architecture x86_64:". If I add static to inline function in add.h or add declaration "extern int add(int, int);" to "adddouble.c", it compiles successfully without errors. I am new to inline function, I don't know how to explain and understand this behaviour. thanks

Lucas Hu
  • 159
  • 1
  • 1
  • 7
  • 1
    What are your build options? Unless you build in C99 or C11 there isn't the concept of an inline function in C. – StoryTeller - Unslander Monica Dec 07 '15 at 17:40
  • You must compile the header file with the others c files or provide both .h and .c, add.h for the prototype of add and add.c for the code – qleguennec Dec 07 '15 at 17:42
  • +1 Good question. It actually links just fine with g++, but I can't get it to work with gcc (-std=c11). Those add symbols are undefined (U) in both addsquare.o and adddouble.c. g++ instead creates weak symbols (W) for the add function and that's why it links. – Petr Skocik Dec 07 '15 at 17:52
  • With -std=c99, it still does not work. – Lucas Hu Dec 07 '15 at 17:59
  • 1
    See this: [C99 inline function in .c file](http://stackoverflow.com/questions/16245521/c99-inline-function-in-c-file/16245669#16245669). You would have to provide an external definition for `add()`. – P.P Dec 07 '15 at 18:25

1 Answers1

9

According to http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf, it looks like inline functions behave differently in C and C++:

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)

If you don't put static there, you're defining an inline function with external linkage without instantiating an external definition.

extern int add(int, int); instatiates the external definition for that function, and you need to do that exactly once (doesn't matter in which file) for the linking to succeed (or you can mark the inline function static and the problem vanishes).

(In C++ the inline creates weak external definitions in each translation unit so you don't have to worry about marking things static or instantiating exactly one external definition for the inline function--g++ should straightforwardly compile it with for f in *.c; do g++ -c "$f"; done; g++ *.o without any problems.)

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142