Preprocessor in C++

What is preprocessor in C++?

Preprocessing occurs before a program is compiled. Some possible actions are the inclusion of other files in the file being compiled, the definition of symbolic constants and macros, conditional compilation of the program code and conditional execution of the preprocessor directives. All preprocessor directives begin with #, and only whitespace characters may appear before a preprocessor directive on a line, Pre-processor directives are not C++ statements, so they do not end in a semicolon(;).Preprocessor directives are processed fully before compilation begins.

Placing a semicolon at the end of a preprocessor directive can lead to a variety of errors, depending on the type of preprocessor directive.

Many preprocessors features(especially macros) are more appropriate for C programmers than for C++ programmers.C++ programmers should familiarize themselves with the pre-processor, because they might need to work with C legacy code.

The directives in C++ are the following

1.#include Preprocessor Directive
2.#define Preprocessor directive: Symbolic Constants
3.#define Preprocessor Directive: Macros
4.Conditional Compilation
5.#error and #pragma Preprocessor Directives
6.# and ## Operators
7.Line Number directives
8.Predefined Symbolic Constants
9.Assertions

#include Preprocessor Directive in C++

The #include preprocessor directive has been used throughout this text. The #include directive causes a copy of a specified file to be included in the place of the directive. The two forms of the #include directive are

#include<filename>
#include "filename"

The difference between these is the location the preprocessor searches for the file to be included. If the file name is enclosed in angle brackets(<and>) used for the standard library header files the preprocessor searches for the specified file in an implementation-dependent manner, normally through predesignated directories. If the file name is enclosed in quotes, the preprocessor searches first in the same directory as the file being compiled, then in the same implementation-dependent manner as for a file name enclosed in angle brackets. This method is normally used to include programmer-defined header files.

Application of #include directive in C++

  • The #include directive is used to include standard header files such as <iostream> and <iomanip>
  • The #include directive is also used with programs consisting of several source files that are to be compiled together.
  • A header file containing declarations and definitions common to the separate program files is often created and included in the file
  • Examples of such declarations and definitions are classes, structures, unions, enumeration and function prototypes, constants and stream objects

#define Preprocessor directive: Symbolic Constants in C++

The #define preprocessor directive creates symbolic constants. Constants represented as symbols and macros operations defined as symbols. The #define preprocessor directive format is

#define identifier replacement-text

When this line appears in a file, all subsequent occurrences(except those inside a string) of the identifier in that file will be replaced by replacement-text before the program is compiled. Example of Symbolic Constants,

#define PI 3.14159

Using symbolic constants in a file other than the file in which the symbolic constants are defined is a syntax error.

Using meaningful names for symbolic constants helps make programs more self-documenting

#define Preprocessor Directive: Macros in C++

A macro is an operation defined in a #define preprocessor directive. As with symbolic constants, the macro-identifier is replaced with the replacement-text before the program is compiled. Macros may be defined with or without argument. A macro without arguments is processed like a symbolic constant. In a macro with arguments, the arguments are substituted in the replacement-text, then the macro is expanded i.e. the replacement text replaces the macro-identifier and argument list in the program.

Now consider the following macro definition with one argument for the area of a circle:

#define CIRCLE_AREA(x)(PI*(x)*(x))

Forgetting to enclose macro arguments in parentheses in the replacement text is an error

Macros can sometimes be used to replace a function call with inline code prior to execution time. This eliminates the overhead of a function call. Inline functions are preferable to macros because they offer the type-checking services of functions.

#undef directives explanation

Symbolic constants and macros can be discarded using the #undef preprocessor directive. Directive #undef “undefines” a symbolic constant or macro name. The scope of a symbolic constant or macro is from its definition until it is either undefined with #undef or the end of the file is reached. Once undefined, a name can be redefined with #define.

Conditional Compilation in C++

  • It enables the programmer to control the execution of preprocessor directives and the compilation of program code
  • Each of the conditional preprocessor directives evaluates a constant integer expression that will determine whether the code will be compiled
  • Cast expression,sizeof expressions, and enumeration constants cannot be evaluated in preprocessor directives.

The conditional preprocessor construct is much like the if selection structure. Example of Conditional Compilation is given below:

#ifndef NULL
#define NULL 0
#endif

#error and #pragma Preprocessor Directives in C++

The #error directive

#error token

prints an implementation-dependent message including the tokens specified in the directive. The tokens are sequences of characters separated by spaces. For example,

#error 1-Out of range error

contains six tokens. In one popular C++ compiler, for example, when a #error directive is processed, the tokens in the directive are displayed as an error message, preprocessing stops and the program does not compile.

The #pragma directive
#pragma tokens

causes an implementation-defined action. A pragma not recognized by the implementation is ignored. A particular C++ compiler, for example, might recognize pragmas that enable the programmer to take advantage of that compiler’s specific capabilities.

# and ## Operators in C++

The # and ## preprocessor operators are available in C++ and ANSI C.The # operator causes a replacement-text token to be converted to a string surrounded by quotes. Consider the following macro definition:

#define HELLO(x)cout<<"Hello,"#x<<endl;

When HELLO(John) appears in a program file, it is expanded to

cout<<"Hello,John"<<endl;

The string “John” replaces #x in the replacement text. Strings separated by whitespace are concatenated during preprocessing, so the above statement is equivalent to

cout<<"Hello,John"<<endl;

Line Number directives in C++

The #line preprocessor directive causes the subsequent source code line to be renumbered starting with the specified constant integer value. The directive

#line 100

starts line numbering from 100, beginning with the next source code line. A file name can be included in the #line directive. The directive

#line 100 "file.cpp"

The above code indicates that lines are numbered from 100, beginning with the next source code line and that the name of the file for the purpose of any compiler message is “file.cpp”.The directive could be used to help make the messages produced by syntax errors and compiler warnings more meaningful. The numbers do not appear in the source file.

Predefined Symbolic Constants in C++

There are six predefined symbolic constants. The identifiers for each predefined symbolic constant begin and end with two underscores. These identifiers and the defined preprocessor operator cannot be used in #define or #undef directives.

Symbolic Constant

Assertions in C++

The assert macro defined in the <cassert> header file tests the value of an expression. If the value of the expression is 0(i.e. false), then assert prints an error message and calls function abort(of the general utility library <cstdlib>) to terminate the program execution. This is a useful debugging tool for testing whether a variable has a correct value. For example, suppose variable x should never be larger than 10 in a program. An assertion may be used to test the value of x and print an error message if the value of x is incorrect. The statement would be.

assert(x<=10);
Symbolic constantDescription
_LINE_ The line number of the current source code line(an integer constant).
_FILE_ The presumed name of the source file(a string)
_DATE_ The date the source file is compiled(a string of the form “Mmm ddd yyy” such as “Aug 19 2002”)
_STDC_ Indicates whether the program conforms to the ANSI C standard.Contains value 1 if there is full conformance and is undefined otherwise.
_TIME_The time the source file is compiled(a string literal of the form”hh:mm:ss”)
_TIMESTAMP_ The date and time of the last modification to the source file(a string of from “Ddd Mmm Date hh:mm:ss yyyy”)

Translate »