In C, both variables and functions have external linkage at file scope by default. Why is the keyword extern only required for variables but not functions that are defined elsewhere? Note that there are two aspects to this question. Given that declarations at file scope default to external linkage:
- Why historically is there no distinction for functions in whether their declaration has externor not? Or, why objectively is no such distinction needed?
- Why historically is there a distinction for variables in whether their declaration has externor not? Or, why objectively is such a distinction needed?
For a minimal example, let's use the following two source files (tu stands for "translation unit").
tu1.c:
extern int i = 123;
tu2.c:
#include <stdio.h>
extern int i;
int main(void) {
  //extern int i;
  ++i;
  printf("%d\n", i);
  return 0;
}
We can compile them with GCC as follows:
gcc -c tu1.c
gcc -c tu2.c
gcc -o myprogram tu1.o tu2.o
(GCC issues the warning 'i' initialized and declared 'extern' for the first command, because it erroneously believes that extern "should be reserved for non-defining declarations". We can safely ignore it.)
Let's compare how the compiler behaves for slightly different versions of the source code:
- extern int i;at file scope in- tu2.c(no change to the above code):
 The output of- myprogramis- 124, as expected.
- extern int i;in- main(instead of at file scope) in- tu2.c:
 This works equally well (but this style is not recommended: "A function should never need to declare a variable using- extern.").
- not declaring ianywhere intu2.c:
 This doesn't work; for linei++;we get the following error:'i' undeclared (first use in this function).
- int i;without- externat file scope in- tu2.c:
 This fails with an error:- multiple definition of `i'.
I am wondering about the rationale for the last case: If a bare (extern-less) int i; defaults to external linkage, why do we need to supply the keyword extern explicitly? The answer seems to be in the standard (C99: 6.9.2 External object definitions), according to which int i; is a tentative definition, instantiated to an actual definition upon compilation. The logic would be that supplying the extern keyword instructs the compiler to treat the resulting construct as a declaration-which-is-not-a-definition. But if this is so: Why doesn't the same logic hold for function prototypes, for which it is well-known that extern is implicit?
I have a feeling that the right answer is related or close to this answer to "What is the rationale behind tentative definitions in C?", but I would like to know what would specifically go wrong if variables and functions were treated the same in the above regard.
There is a similar question about C++ and a relevant article by Peter Goldsborough.
Note for people used to programming in C++:
- In C, variables at file scope (incl constones) and functions default to external linkage.
- In C++, there is the subtle difference that constglobal variables default to internal linkage.
 
     
     
    