Consider:
Makefile
OPT = -O3
CFLAGS = $(OPT) -Wall -Wextra
CC = gcc
default: main.c a.c b.c
$(CC) $(OPT) $^ -o exec
a.h
#ifndef A_H
#define A_H
inline
int f()
{
return 0;
}
#endif
a.c
#include "a.h"
// extern inline int f();
b.c
#include "a.h"
int g()
{
return f();
}
main.c
#include "a.h"
int main () {
return f();
}
This compiles as is. When OPT = -O0
this fails:
"_f", referenced from: _main in ccSN57dj.o ld: symbol(s) not found for architecture x86_64 collect2: error: ld returned 1 exit status
when the line in a.c
is commented out, this compiles again.
I have read:
- Order of `static` definition and `extern declaration` in a translation unit
- How to properly inline and use an inline function in C99, correcting link failure?
- How do I use extern to share variables between source files?
- What does extern inline do?
- What is the use of the `inline` keyword in C?
- Is "inline" without "static" or "extern" ever useful in C99?
- Inline functions in C
I understand the reason for this is that the inline definitions emit no object code and at lower optimization levels they are not inlined, so there is no definition to be found at linkage.
Referencing:
A function where at least one declaration mentions inline, but where some declaration doesn't mention inline or does mention extern. There must be a definition in the same translation unit. Stand-alone object code is emitted (just like a normal function) and can be called from other translation units in your program.
This is why commenting out the line in a.c
works.
My question is multi-fold:
- I've learned that the
extern
keyword states that something is defined in another module, so why is it okay for it to be defined in the same? Are there different interpretations ofextern
? - Why is it okay for there to be multiple definitions, spawned from the different inline definitions in the header files? If none of these qualify as an
external definition
then why does this method compile with no warnings and provide a definition when runningobjdump -d
? - How would it be chosen between these multiple definitions if they were not the same, given this ambiguity?
The second one is the more puzzling, since according to C 2018 6.7.4 7 :
An inline definition does not provide an external definition for the function, ...
but the code compiles with no warnings.