After the C pre-processor has included all the header files and expanded all macros, the compiler can compile the program. It does this by turning the C source code into an object code file, which is a file ending in .o which contains the binary version of the source code. Object code is not directly executable, though. In order to make an executable, you also have to add code for all of the library functions that were #included into the file (this is not the same as including the declarations, which is what #include does). This is the job of the linker.

In general, the exact sequence how to invoke a C compiler depends much on the system that you are using. Here we are using the GCC compiler, though it should be noted that many more compilers exist:

% gcc -Wall -c foo.c

% is the OS’ command prompt. This tells the compiler to run the pre-processor on the file foo.c and then compile it into the object code file foo.o. The -c option means to compile the source code file into an object file but not to invoke the linker. This option -c is available on POSIX systems, such as Linux or macOS; other systems may use different syntax.

If your entire program is in one source code file, you can instead do this:

% gcc -Wall foo.c -o foo

This tells the compiler to run the pre-processor on foo.c, compile it and then link it to create an executable called foo. The -o option states that the next word on the line is the name of the binary executable file (program). If you don’t specify the -o, (if you just type gcc foo.c), the executable will be named a.out for historical reasons.

In general the compiler takes four steps when converting a .c file into an executable:

  1. pre-processing - textually expands #include directives and #define macros in your .c file
  2. compilation - converts the program into assembly (you can stop the compiler at this step by adding the -S option)
  3. assembly - converts the assembly into machine code
  4. linkage - links the object code to external libraries to create an executable

Note also that the name of the compiler we are using is GCC, which stands for both “GNU C compiler” and “GNU compiler collection”, depending on context. Other C compilers exist. For Unix-like operating systems, many of them have the name cc, for “C compiler”, which is often a symbolic link to some other compiler. On Linux systems, cc is often an alias for GCC. On macOS or OS-X, it points to clang.

The POSIX standards currently mandates [c99](<http://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html>) as the name of a C compiler — it supports the C99 standard by default. Earlier versions of POSIX mandated [c89](<http://pubs.opengroup.org/onlinepubs/7990989775/xcu/c89.html>) as the compiler. POSIX also mandates that this compiler understands the options -c and -o that we used above.


Note: The -Wall option present in both gcc examples tells the compiler to print warnings about questionable constructions, which is strongly recommended. It is a also good idea to add other warning options, e.g. -Wextra.