The Compile–Link–Load Toolchain

the C runtime startup (crt0)

/ C-R-T-zero /

Beginners often believe that running a C program starts at main, that main is the very first thing to execute. It is not quite true. Before your main function runs, a small piece of code provided by the system has already been working to set the stage, and it is that hidden code, not the loader and not you, which finally calls main. This startup code is traditionally named crt0 (C run-time, object 0), and it is quietly linked into every ordinary C program.

Here is what happens at a glance. The loader maps the program into memory and jumps not to main but to the program's true entry point, a label often called _start, which sits inside the startup code. That code does the housekeeping main takes for granted: it makes sure the stack is set up correctly, collects the command-line arguments and environment the kernel handed over and arranges them as argc, argv, and the environment, runs any initialisers that must happen before main (for instance constructors of certain global objects), and only then calls main with those arguments. When main returns its int value, the startup code does not just stop: it takes that return value, runs clean-up routines, and calls exit so the value becomes the program's exit status reported to the shell.

Knowing this demystifies several things. It explains why main can simply return a number and yet the program 'tells the shell' that number: the startup code carried it to exit for you. It explains why _start, not main, is the real entry point recorded in the executable. And it is why, in unusual freestanding or embedded settings where there is no crt0, you must provide your own startup and main is genuinely not enough on its own. You normally never write or even see this code; the toolchain links the right crt0 for your platform automatically.

// what you write: what really happens at run time: int main(void) { _start: // true entry point (crt0) return 0; set up stack, argc, argv, environment } call main() // <- main runs here exit( return value ) // <- becomes exit status

main is not the first code to run; the startup code sets up arguments and then calls it.

main is not the program's true entry point: the linker records _start (inside crt0), which sets up argc/argv and calls main, then turns main's return value into the process exit status.

Also called
crt0C runtimestartup code啟動碼