I learned from my colleague that one can write and execute a C program without writing a main() function. It can be done like this:


/* Compile this with gcc -nostartfiles */

#include <stdlib.h>

void _start() {
  int ret = my_main();

int my_main() {
  puts("This is a program without a main() function!");
  return 0; 

Compile it with this command:

gcc -o my_main my_main.c –nostartfiles

Run it with this command:


When would one need to do this kind of thing? Is there any real world scenario where this would be useful?


The symbol _start is the entry point of your program. That is, the address of that symbol is the address jumped to on program start. Normally, the function with the name _start is supplied by a file called crt0.o which contains the startup code for the C runtime environment. It sets up some stuff, populates the argument array argv, counts how many arguments are there, and then calls main. After main returns, exit is called.

If a program does not want to use the C runtime environment, it needs to supply its own code for _start. For instance, the reference implementation of the Go programming language does so because they need a non-standard threading model which requires some magic with the stack. It's also useful to supply your own _start when you want to write really tiny programs or programs that do unconventional things.

  • 2
    Another example is Linux's dynamic linker/loader which has its own _start defined. – P.P. Apr 17 '15 at 10:52
  • 2
    @BlueMoon But that_start comes from the object file crt0.o, too. – fuz Apr 17 '15 at 10:56
  • 2
    @ThomasMatthews The standard doesn't specify _start; in fact, it doesn't specify what happens before main is called at all, it just specifies what conditions must be met when main is called. It's more a convention for the entry point to be _start which dates back to the old days. – fuz Apr 17 '15 at 19:18
  • 1
    "the reference implementation of the Go programming language does so because they need a non-standard threading model" crt0.o is C specific (crt->C runtime). There's no reason to expect it to be used for any other language. And Go's threading model is completely standard compliant – Steve Cox Apr 17 '15 at 20:19
  • 5
    @SteveCox Many programming language are built on top of the C runtime because it's easier to implement languages this way. Go does not use the normal threading model. They use small, heap-allocated stacks and their own scheduler. This is certainly not a standard threading model. – fuz Apr 17 '15 at 20:34

While main is the entry point for your program from a programmers perspective, _start is the usual entry point from the OS perspective (the first instruction that is executed after your program was started from the OS)

In a typical C and especially C++ program, a lot of work has been done before the execution enters main. Especially stuff like initialization of global variables. Here you can find a good explanation of everything that's going on between _start() and main() and also after main has exited again (see comment below).
The necessary code for that is usually provided by the compiler writers in a startup file, but with the flag –nostartfiles you essentially tell the compiler: "Don't bother giving me the standard startup file, give me full control over what is happening right from the start".

This is sometimes necessary and often used on embedded systems. E.g. if you don't have an OS and you have to manually enable certain parts of your memory system (e.g. caches) before the initialization of your global objects.

  • The global vars are part of the data section and thus are setup during the loading of the program (if they are const they are part of the text section, same story). The _start function is completely unrelated to that. – Cheiron Apr 17 '15 at 13:33
  • @Cheiron: Sorry, my emistake In c++, global variables are often initialized by a constructor which is run inside _start() (or actually another function called by it) and in many Bare-Metal-Programs, you explicitly copy all global data from flash to RAM first, which also happens in _start(), but this question was neither about c++ nor bare-metal code. – MikeMB Apr 17 '15 at 15:04
  • 1
    Note that in a program that supplies its own _start, the C library won't get initialized unless you take special steps to do it yourself -- it may well be unsafe to use any non-async-signal-safe function from such a program. (There's no official guarantee that any library function will work, but async-signal-safe functions can't refer to any global data at all, so they'd have to go out of their way to malfunction.) – zwol Apr 17 '15 at 17:59
  • @zwol that's only partially correct. For instance, such a function might allocate memory. Allocating memory is problematic when the internal data structures for malloc are not initialized. – fuz Apr 17 '15 at 19:20
  • 1
    @FUZxxl Having said that, I notice that async-signal-safe functions are allowed to modify errno (e.g. read and write are async-signal-safe and can set errno) and that could conceivably be a problem depending on exactly when the per-thread errno location is allocated. – zwol Apr 17 '15 at 19:39

_start() is function which is pointed by the special header , for just to be understood by the computer. But It is important because we should learn what is going happen at the backside of the computer.

Your Answer

