C extern functions

Earlier I showed the C extern keyword applied to variable declarations. More generally, extern can be applied to declarations. There are two kinds of thing you can declare in C: variables and functions. So the extern keyword can also be applied to function declarations. For example:

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

Applied to a function declaration, the extern keyword in fact does nothing: the declaration extern int incr(int) is exactly the same as int incr(int). This is because all function declarations have an implicit extern applied! This also applies to function definitions: the function definition int incr(int x) { return x+1; } is implicitly extern int incr(int x) { return x+1; }. So, you have been using extern, whether you knew it or not.

For this reason, the following program yields an ugly linker error instead of a compiler error:

#include <stdio.h>
int incr(int);
int main() {
  printf("incr(5) = %d\n", incr(5));
}
$ clang main.c
Undefined symbols for architecture x86_64:
  "_incr", referenced from:
      _main in main-b06e2c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Why is it the case that all C function declarations are implicitly extern? If it were possible to declare a C function without making it extern, the above program could generate a higher-level compiler error, like this:

$ clang main.c
main.c:2:1: error: function 'incr' declared but not defined
  int incr(int);

In fact, it is possible to declare a non-extern function, and it is done with the static keyword:

#include <stdio.h>
static int incr(int);
int main() {
  printf("incr(5) = %d\n", incr(5));
}
$ clang main.c
main.c:2:12: warning: function 'incr' has internal linkage but is not defined [-Wundefined-internal]
static int incr(int);
           ^
main.c:4:28: note: used here
  printf("incr(5) = %d\n", incr(5));

In effect, static undoes the work of the implicit extern. In my opinion this is a flaw in the C language. The semantics should be the same as with C variables: default to non-external; become external when extern is applied. The static keyword then becomes unnecessary.

  externed?
int incr(int); yes, but this is a language flaw
extern int incr(int); yes
static int incr(int); no, but this shouldn’t be necessary
static extern int incr(int); this is not possible

I wrote this because I felt like it. This post is my own, and not associated with my employer.

Jim. Public speaking. Friends. Vidrio.