Every C program needs a main function — that is where the C runtime hands control to your code. But what if you want to write a program without typing main in the source? The answer is a preprocessor macro: #define maps any identifier you choose to main before compilation, so the compiler and linker see exactly what they need without you ever writing the word main.
How the Macro Trick Works
The C preprocessor runs before compilation. When you write:
#define start main
Every occurrence of the token start in the file is replaced with main. So when you write:
int start(void) { ... }
The preprocessor produces:
int main(void) { ... }
The compiler and linker never see start — they only see main, which is the required entry point. The source file never contains the word main, but the preprocessed output does.
Program 1 – Using start as the Entry Point
#include <stdio.h>
#define start main
int start(void)
{
printf("Running without 'main' in the source code.\n");
printf("The preprocessor replaced 'start' with 'main'.\n");
return 0;
}
Output
Running without 'main' in the source code. The preprocessor replaced 'start' with 'main'.
Program 2 – Using begin as the Entry Point
#include <stdio.h>
#define begin main
int begin(void)
{
int i;
printf("Program entry point: begin()\n");
for (i = 1; i <= 3; i++)
printf("Count: %d\n", i);
return 0;
}
Output
Program entry point: begin() Count: 1 Count: 2 Count: 3
How to Compile and Run
gcc -ansi -Wall -Wextra no_main1.c -o no_main1
./no_main1
You can verify what the preprocessor produces with the -E flag — it prints the preprocessed source without compiling:
gcc -E no_main1.c
The output shows int main(void) even though the source says int start(void).
Why main Must Exist
When your program starts, the operating system calls the C runtime startup code (often called _start or crt0). That startup code calls main by name. The linker looks for a symbol named main in the compiled object files. If no main symbol exists, linking fails with an “undefined reference to main” error. The macro trick satisfies the linker because the preprocessor inserts main before the compiler ever runs.
What This Is — and Is Not
| Claim | Reality |
|---|---|
Running without main |
The binary still has a main symbol — the macro inserts it |
| Bypassing the C runtime | No — startup/teardown still runs normally |
| Practical use in production | None — this is a language curiosity and a preprocessor demonstration |
| Useful for learning | Yes — shows how the preprocessor works before compilation |
This technique appears in interview questions and coding puzzles to test whether you understand the role of the C preprocessor. It is not used in real programs — naming your entry point main is always clearer.
Related Programs
- C Preprocessor Directives – #define, #if, #ifdef with Examples
- C #define Macro – Object-Like, Function-Like, and Conditional Macros
- Pointers in C – Complete Guide
- Binary Search in C
Recommended Books
- The C Programming Language – Kernighan & Ritchie (India) | Amazon.com
- C Programming: A Modern Approach – K.N. King (India) | Amazon.com
Practice C with the C Programming Quiz App — 500+ MCQs covering preprocessor macros, pointers, and more.
Download on Google Play →