6

Even though this might look like duplication, I'd claim that it isn't.

Why does a compiler make the Foo function, which is defined in foo.c as inline double Foo() { return 1.2; }, a global function if the foo.c file also has the extern double Foo(); line anywhere?

Please see the example with foo.c and main.c:

// foo.c
#if defined(WITH_DECL)
extern double Foo();
#endif

inline double Foo() {
  return 1.2;
}

double Bar() {
  printf("%lf\n", Foo());
  return Foo() + Foo();
}

And,here's main.c:

double Foo();
double Bar();
int main() {
  printf("Bar + Foo = %lf + %lf\n", Bar(), Foo());
  return 0;
}

Here's how I built:

clang -O2 main.c foo.c
clang -O2 main.c foo.c -DWITH_DECL

The first command failed. The second command silently succeeded.

I understand why the first failed. As expected it's a linker error:

clang -g3 -O0 -std=c11 foo.c main.c -Wall -Werror -O2
/usr/bin/x86_64-pc-linux-gnu-ld.bfd: /usr/bin/x86_64-pc-linux-gnu-ld.bfd: DWARF error: mangled line number section (bad file number)
/tmp/main-10e175.o: in function `main':
/home/aion1223/workspace/prac/main.c:7:(.text+0x8): undefined reference to `Foo'
clang: error: linker command failed with exit code 1 (use -v to see invocation)`

I do not understand why the second command does not fail.

First, do I expect this to happen for all standard-complying compilers? Second, why at least some of my compilers silently build the executable when -DWITH_DECL is given?

I'd like to figure out if this is something that I can rely on, or it just happened so but is not guaranteed by C language standard.

The standard I tried is c99, c11, and c17. The compilers are clang 20, gcc14, and gcc12.

7
  • "...so but is not guaranteed by C language standard...", - please use -std=. we will know what standard you refer to. Commented Aug 29 at 3:59
  • For now, I used c11. Just tried c99 and c17. Got the same result. Commented Aug 29 at 4:00
  • You should use @ with commenter name when you answer to that specific comment. otherwise I will not see that you have answered. Commented Aug 29 at 4:01
  • @iam_ai_copy-paste I see. Thank you! Yeah, it was C99, C11, and C17 with clang20 and gcc9/12/14. All on Linux x86_64. Commented Aug 29 at 4:04
  • overall, i think you asked a question that is indeed should be backed by some standard references. apart from that, what do you want from inline keyword? I think, in C language it is not so useful as in C++. Commented Aug 29 at 4:08

1 Answer 1

5

Starting with C99, if a function is defined inline without any extern or static declarations, it is an inline definition. This means it can't be used outside of the current translation unit.

By adding an extern declaration (which doesn't actually require the extern keyword), it becomes an external definition that can be used outside of the translation unit.

This is spelled out in section 6.7.5p7 of the C standard:

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 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. Inline definitions provide an alternative to external definitions, 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.

So to summarize, what you're seeing is expected for a compiler in C99 mode or later.

On a side note, some compilers won't include an inline definition at all and will generate link errors in the translation unit it was defined in unless certain options are passed in. For example, gcc will generate linker errors for references in foo.c with -O0 but not -O1 or higher.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.