Here is a simple “Hello, World!” program in C.
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}The program is written in the C11 standard. The previous version was C99. The standards are largely backward compatible: a C99 program compiled with a C11 compiler will still work. The opposite is not always possible, because there can be changes that the previous standards did not have.
To compile the program, run
gcc -std=c11 ./main.c -o mainThe command generates a main file, which is an executable binary. Run it with
./mainand it prints Hello, World!. The \n at the end of the string is an escape sequence, covered in the next note.
The program includes the header file stdio.h, which provides the functions and macros needed to interact with standard input and output. In C, most things are functions. The entry point of a C program is the main() function, and int main() is the conventional way to define it. The return 0; indicates that the program completed successfully. Anything other than 0 indicates an error or abnormal termination. This return value can be used by other programs, like the shell, to perform further operations.
How a C Program Is Converted
When you run the gcc command, the program is not directly converted into a binary. It goes through several intermediary steps. To see them, run
gcc -std=c11 -save-temps ./main.c -o mainThis produces four files: main, main.i, main.s, and main.o.
flowchart LR A["main.c"] --> B["Preprocessor"] B -.-> F["main.i"] B --> C["Compiler"] C -.-> G["main.s"] C --> D["Assembler"] D -.-> H["main.o"] D --> E["Linker"] E -.-> I["main"]
| Stage | Tool / Process | Output file | Description |
|---|---|---|---|
| 1 | Source code | main.c | Original C source code |
| 2 | Preprocessor | main.i | Expands macros and header files |
| 3 | Compiler | main.s | Converts preprocessed C into assembly |
| 4 | Assembler | main.o | Converts assembly into machine code |
| 5 | Linker | main | Links object files and libraries into an executable |
If you inspect main.i, you can see that the #include <stdio.h> declaration was expanded above the main function. This is then transformed into assembly code in main.s, which the assembler converts into machine code in main.o. Finally, the linker links the external libraries and their implementations to produce the executable.
Note
main.icontains only the declarations from the header files, not the actual implementations. The implementations are linked by the linker.
Next up: Escape Sequences