Table of Contents

Compiler

A compiler is responsible for translating code written in a high level language into code in a lower level language. We use the compiler to turn c++ code an executable program.

The compiler we use is the GNU c++ compiler, g++.

Note that on many systems g++ can also be invoked using c++.

This is a very complex piece of software capable of compiling multiple high level programming languages into machine language and assembly language on many different architectures and operating environments. The following is a very simplified overview.

A Note on Examples

In the following discussion, examples of using the compiler at the command line will be given. These examples were produced using bash as the shell.

In the following session, the user typed the ls command. Note, the shell supplied the $, it was not typed by the user.

$ ls
a.out*  hello.cpp

Basic Usage

By default the compiler takes a single argument, the name of the file containing code you wish to compile. If the compile is successful, the executable program will be stored in the file a.out.

$ ls
hello.cpp
$ g++ hello.cpp
$ ls
a.out*  hello.cpp
$ ./a.out

In this example:

  1. The user typed ls to show the files in the current working directory.
    1. The shell responded by showing hello.cpp was the only file the the directory.
  2. The user then typed g++ hello.cpp
    1. The g++ produced no output to the screen.
    2. This means that the program compiled successfully.
  3. The user typed ls again.
    1. The file a.out appeared in the directory.
    2. This is the executable program produced by compiling hello.cpp
  4. The user then typed ./a.out to execute the program.
    1. Any output produced by the program would be displayed next.

Syntax Errors

Syntax errors are produced when the code is not in the proper format. Syntax errors are a side effect of the compiler.

When a compiler encounters a syntax error it will:

In addition, the compiler will possibly report additional syntax errors. These errors may or may not be valid. It is always best to fix the first syntax error the compiler reports.

If the following code is compiled:

#include <iostream>
 
using namespace std;
 
int main() {
    // the second quotation is missing on the next line.
    cout << "Hello World! << endl;
 
    return 0;
}

The following syntax errors might be reported:

$ g++ hello.cpp
hello.cpp:7:13: warning: missing terminating " character
    7 |     cout << "Hello World! << endl;
      |             ^
hello.cpp:7:13: error: missing terminating " character
    7 |     cout << "Hello World! << endl;
      |             ^~~~~~~~~~~~~~~~~~~~~~
hello.cpp: In function 'int main()':
hello.cpp:9:5: error: expected primary-expression before 'return'
    9 |     return 0;
      |     ^~~~~~

The compiler has detected the syntax error on line 7, but also produces a error on line 9. There is no error on line 9. Removing the error on line 7 will remove this incorrectly reported error as well.

Note: The compiler will not produce an executable if a syntax error is encountered.

Warnings

In addition to syntax errors, compilers can also produce warnings. A warning is produced when the compiler discovers a section of code which is syntactically correct, but likely to produce an error when the program is run.

Compiling the following code:

#include <iostream>
 
using namespace std;
 
int main() {
 
   cout << "3/0 = " << 3/0 << endl;
 
   return 0;
}

Might produce the following:

$ g++ divide.cpp
divide.cpp: In function 'int main()':
divide.cpp:7:25: warning: division by zero [-Wdiv-by-zero]
    7 |    cout << "3/0 = " << 3/0 << endl;
      |                        ~^~

Note that the compiler will still produce an executable.

Good programming practices says you should remove most if not all warnings from your code.

Warnings will depend on the flags passed to the compiler. This is discussed later.

Command Line Arguments

Command line arguments allow the user to control how the compiler operates. These are typed following the command (g++ or c++) and are sometimes called flags.

The first command line argument for g++ that many users encounter is the -o flag. This flag is used to tell the compiler to name the output file something other than a.out. Renaming the output file allows users to identify the use of the executable or possibly the source code for the executable.

The -o flag is accompanied by the name of the output file the user wishes to produce. It is normal to compile the source code hello.cpp into an executable named hello. This is done in the following example:

$ ls
hello.cpp
$ g++ -o hello hello.cpp
$ ls
hello*  hello.cpp
$ ./hello

Note that the output is called hello and not hello.cpp. If the user were to allowed to do this, the source code in hello.cpp would be replaced with the new executable just produced. The current version of g++ will not allow this to happen.

$ g++ -o hello.cpp hello.cpp
g++: fatal error: input file 'hello.cpp' is the same as output file
compilation terminated.

g++ supports many flags. These include

On most linux systems man g++ will show documentation for the flags supported by your version of g++.

Some Useful Arguments

Producing Additional Warnings

Compilers are also capable of analyzing source code to predict where this code may cause run time errors. By turning on these warnings you are more likely to write code that conforms to the standard and less likely to have common runtime errors in your code.

Your instructor may require one or more of the following flags when compiling code:

Note: There are many other warning producing flags.

For the following code:

#include <iostream>
 
using namespace std;
 
int main() {
    int a,b;
    int c;
 
    if (a = b)
       cout << " a is 4" << endl;
       a = 5;
 
    return 3.14;
}

Compiling without additional flags produces no warnings. But compiling with the listed flags produces

$ g++ bad.cpp
$ g++ -g -O3 -Wpedantic -Wall -Wextra -Wmisleading-indentation -Wunused -Wuninitialized -Wshadow -Wconversion bad.cpp
bad.cpp: In function 'int main()':
bad.cpp:10:11: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
   10 |     if (a = b)
      |         ~~^~~
bad.cpp:10:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
   10 |     if (a = b)
      |     ^~
bad.cpp:12:8: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
   12 |        a = 5;
      |        ^
bad.cpp:14:12: warning: conversion from 'double' to 'int' changes value from '3.1400000000000001e+0' to '3' [-Wfloat-conversion]
   14 |     return 3.14;
      |            ^~~~
bad.cpp:8:9: warning: unused variable 'c' [-Wunused-variable]
    8 |     int c;
      |         ^
bad.cpp:10:11: warning: 'b' is used uninitialized in this function [-Wuninitialized]
   10 |     if (a = b)
      |         ~~^~~

You should use all command line flags specified by your instructor.

Note: If you wish to avoid typing command line arguments, you may wish to investigate

Other Arguments

Other flags are useful in different situations.