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 main

The command generates a main file, which is an executable binary. Run it with

./main

and 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 main

This 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"]
StageTool / ProcessOutput fileDescription
1Source codemain.cOriginal C source code
2Preprocessormain.iExpands macros and header files
3Compilermain.sConverts preprocessed C into assembly
4Assemblermain.oConverts assembly into machine code
5LinkermainLinks 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.i contains only the declarations from the header files, not the actual implementations. The implementations are linked by the linker.

Next up: Escape Sequences