Since the question is double-tagged as C and C++, the reasoning for C++ and C would be different:
- C++ uses name mangling to help linker distinguish between textually identical symbols of different types, e.g. a global variable
xyz
and a free-standing global functionxyz(int)
. However, the namemain
is never mangled. - C does not use mangling, so it is possible for a program to confuse linker by providing a symbol of one kind in place of a different symbol, and have the program successfully link.
That is what’s going on here: the linker expects to find symbol main
, and it does. It “wires” that symbol as if it were a function, because it does not know any better. The portion of runtime library that passes control to main
asks linker for main
, so linker gives it symbol main
, letting the link phase to complete. Of course this fails at runtime, because main
is not a function.
Here is another illustration of the same issue:
file x.c:
#include <stdio.h>
int foo(); // <<== main() expects this
int main(){
printf("%p\n", (void*)&foo);
return 0;
}
file y.c:
int foo; // <<== external definition supplies a symbol of a wrong kind
compiling:
gcc x.c y.c
This compiles, and it would probably run, but it’s undefined behavior, because the type of the symbol promised to the compiler is different from the actual symbol supplied to the linker.
As far as the warning goes, I think it is reasonable: C lets you build libraries that have no main
function, so the compiler frees up the name main
for other uses if you need to define a variable main
for some unknown reason.