CSE 202: Computer Science II, Winter 2018
Preprocessor

The preprocessor is a program that is a part of, or built into, every C++ compiler. It is responsible for processing all preprocessor directives in your source code.

A preprocessor directive is any line that begins with the # character. #include <iostream> is a preprocessor directive.

#include

The include directive takes the contents of a file (typically a C++ header file), and inserts it into the current file at the current line.

If the filename is enclosed in angle brackets (for example: #include <iostream>), then the file is searched for in the standard include directories ("standard" relative to the operating system or compiler). When including standard header files such as iostream, string, and cmath, then you would use angle brackets in the include directive.

If the filename is enclosed in double quotes (for example: #include "common.h"), then the file is searched for relative to the directory in which the current source file resides. When including your own header files in your own project, then double quotes should be used in the include directive.

#error

The error directive stops compilation and displays an error message. For example: #error This header file is obsolete. Please use the newest version.

#define and #undef

#define is used to create object-like macros and function-like macros.

A line such as #define PROJECT_VERSION 1.1 will replace all occurrences of the identifier PROJECT_VERSION with 1.1 in all of your source code, regardless of the scope in which they occur. The directive #undef PROJECT_VERSION undefines the macro PROJECT_VERSION which was previously created with #define.

Here are some standard, predefined macros:

Macro Description
__cplusplus The version of C++ standard being used, represented as a long int. Expands to 199711L for C++98, 201103L for C++11, 201402L for C++14, and 201703L for C++17.
__FILE__ Expands to the name of the current file, represented as a null-terminated string literal.
__LINE__ Expands to the current line number, represented as an int
__DATE__ Expands to the current date, represented as a null-terminated string literal in the same format as generated by the function std::asctime
__TIME__ Expands to the current time, represented as a null-terminated string literal in the format "hh:mm:ss".
Conditional preprocessor directives

The __cplusplus macro is especially useful if you want to take advantage of newer C++ features if they are supported.

In the following example, #if, #else, and #endif is used to choose how to initialize a vector type based on the version of C++ we're using:

#if __cplusplus >= 201103L std::vector<int> v{{10, 20, 30}}; #else std::vector<int> v; v.push_back(10); v.push_back(20); v.push_back(30); #endif

C++11 allows a vector variable to be directly initialized with an initializer list. In prior versions of C++ you either have to repeatedly call push_back or call assign with an existing array or container to achieve the same effect. Most compilers use C++98 by default.

The condition of an #if directive must be a constant expression. #elif is also provided as the preprocessor equivalent to an "else if" clause.

The unary function-like operator defined can be used in the condition of #if or #elif to check if a macro is defined. For example, the directive:

#if defined(abs) #undef abs #endif

undefines abs if it exists as a macro. The directive #ifdef X is equivalent to #if defined(X) and #ifndef X is equivalent to #if !defined(X).