Compiling a C program

This chapter describes how to compile C programs using gcc. Programs can be compiled from a single file or from multiple files, using system libraries and header files.

Compilation refers to the process of converting a program from the textual source code in a programming language such as C or C++ into machine code, the sequence of 1's and 0's used to control the central processing unit (CPU) of the computer. This machine code is stored in a file known as an executable file, sometimes referred to as a binary file.

Compiling a simple C program

The classic example program for the C language is Hello World. Here is the source code for our version of the program:


#include <stdio.h>

int
main (void)
{
  printf ("Hello, world!\n");
  return 0;
}

We'll assume the source code is stored in a file called `hello.c'. To compile the file `hello.c' with gcc, use the following command: 
linux1[1]> gcc -Wall hello.c -o hello

This compiles the source code in `hello.c' to machine code and stores it in an executable file `hello'. The output file for the machine code is specified using the -o option. This option is usually given as the last argument on the command-line. If it is omitted, the output is written to a default file called `a.out'.

Note that if a file with the same name as the executable file already exists in the directory it will be overwritten.

The option -Wall turns on the most commonly-used compiler warnings -- it is recommended that you always use this option. Without it the compiler will not produce any warning messages. There are other -W warning options for special cases which will be discussed in later chapters, but -Wall is the most important. Compiler warnings are an essential aid in detecting possible problems when programming in C and C++

In this case the compiler does not produce any warnings with the -Wall option, since the program is completely valid. Source code which does not produce any warnings is said to compile cleanly.

To run the program, type the path name of the executable:

linux1[1]> ./hello
Hello, world!

This loads the executable file into memory and causes the CPU to begin executing the instructions contained within it. The path ./ refers to the current directory, so ./hello loads and runs the executable file `hello' located in the current directory.

Finding errors in a simple program

As mentioned above, compiler warnings are an essential aid when programming in C and C++. To demonstrate this the program below contains a subtle error: it uses the function printf incorrectly by specifying a floating-point format %f for an integer value:


#include <stdio.h>

int
main (void)
{
  printf ("Two plus two is %f\n", 4);
  return 0;
}


This error is not obvious at first sight but can be detected by the compiler. However, in order for it to be reported the warning option -Wall must be turned on.

If the program above is stored in a file `bad.c' and compiled with the warning option -Wall the compiler produces the following message:

linux1[1]> gcc -Wall bad.c -o bad
bad.c: In function `main':
bad.c:6: warning: double format, different 
  type arg (arg 2)

The text of the warning indicates that a format string has been used incorrectly in the file `bad.c' at line 6. The messages produced by gcc always have the form file:line-number:message. The compiler distinguishes between error messages, which prevent the program being compiled, and warning messages which indicate likely problems (but do not stop the program from compiling).

In this case the correct format specifier for displaying integers with printf would be %d (the format specifiers for printf can be found in any general book on C, such as the GNU C Library Reference Manual, see section Further reading).

Without the warning option -Wall the program appears to compile without problems, but produces corrupted results:

linux1[1]> gcc bad.c -o bad
linux1[2]> ./bad
Two plus two is 2.585495    (corrupted output)

The incorrect format specifier causes the output to be corrupted, because the function printf is passed an integer instead of a floating-point number. Integers and floating-point numbers are stored in different formats in memory, and occupy different numbers of bytes, leading to a spurious result.

Clearly it is very dangerous to compile a program without checking for compiler warnings. If there are any functions which are not used correctly they can cause the program to crash or to produce incorrect results. However, turning on the compiler warning option -Wall will catch many of the common errors which occur in C programming.