Why does declaring main as an array compile? Why does declaring main as an array compile? c c

Why does declaring main as an array compile?


It's because C allows for "non-hosted" or freestanding environment which doesn't require the main function. This means that the name main is freed for other uses. This is why the language as such allows for such declarations. Most compilers are designed to support both (the difference is mostly how linking is done) and therefore they don't disallow constructs that would be illegal in hosted environment.

The section you refers to in the standard refers to hosted environment, the corresponding for freestanding is:

in a freestanding environment (in which C program execution may take place without any benefit of an operating system), the name and type of the function called at program startup are implementation-defined. Any library facilities available to a freestanding program, other than the minimal set required by clause 4, are implementation-defined.

If you then link it as usual it will go bad since the linker normally has little knowledge about the nature of the symbols (what type it has or even if it's a function or variable). In this case the linker will happily resolve calls to main to the variable named main. If the symbol is not found it will result in link error.

If you're linking it as usual you're basically trying to use the compiler in hosted operation and then not defining main as you're supposed to means undefined behavior as per appendix J.2:

the behavior is undefined in the following circumstances:

  • ...
  • program in a hosted environment does not define a function named main using one of the specified forms (5.1.2.2.1)

The purpose of the freestanding possibility is to be able to use C in environments where (for example) standard libraries or CRT initialization is not given. This means that the code that is run before main is called (that's the CRT initialization that initializes the C runtime) might not provided and you would be expected to provide that yourself (and you may decide to have a main or may decide not to).


If you are interested how to create program in main array: https://jroweboy.github.io/c/asm/2015/01/26/when-is-main-not-a-function.html. The example source there just contains a char (and later int) array called main which is filled with machine instructions.

The main steps and problems were:

  • Obtain the machine instructions of a main function from a gdb memory dump and copy it into the array
  • Tag the data in main[] executable by declaring it const (data is apparently either writable or executable)
  • Last detail: Change an address for actual string data.

The resulting C code is just

const int main[] = {    -443987883, 440, 113408, -1922629632,    4149, 899584, 84869120, 15544,    266023168, 1818576901, 1461743468, 1684828783,    -1017312735};

but results in an executable program on a 64 bit PC:

$ gcc -Wall final_array.c -o sixthfinal_array.c:1:11: warning: ‘main’ is usually a function [-Wmain] const int main[] = {           ^$ ./sixth Hello World!


The problem is that main is not a reserved identifier. The C standard only says that in hosted systems there is usually a function called main. But nothing in the standard prevents you from abusing the same identifier for other sinister purposes.

GCC gives you a smug warning "main is usually a function", hinting that the use of the identifier main for other unrelated purposes isn't a brilliant idea.


Silly example:

#include <stdio.h>int main (void){  int main = 5;  main:  printf("%d\n", main);  main--;  if(main)  {    goto main;  }  else  {    int main (void);    main();  }}

This program will repeatedly print the numbers 5,4,3,2,1 until it gets a stack overflow and crashes (don't try this at home). Unfortunately, the above program is a strictly conforming C program and the compiler can't stop you from writing it.