Chapter 13 - The Preprocessor
Outline
13.1 Introduction
13.2 The #include Preprocessor Directive
13.3 The #define Preprocessor Directive: Symbolic Constants
13.4 The #define Preprocessor Directive: Macros
13.5 Conditional Compilation
13.6 The #error and #pragma Preprocessor Directives
13.7 The # and ## Operators
13.8 Line Numbers
13.9 Predefined Symbolic Constants
13.10 Assertions
2000 Prentice Hall, Inc. All rights reserved.
13.1 Introduction
• Preprocessing
– Occurs before a program is compiled
– Inclusion of other files
– Definition of symbolic constants and macros
– Conditional compilation of program code
– Conditional execution of preprocessor directives
• Format of preprocessor directives
– Lines begin with #
– Only whitespace characters before directives on a line
2000 Prentice Hall, Inc. All rights reserved.
13.2 The #include Preprocessor Directive
• #include
– Copy of a specified file included in place of the directive
#include <filename> -
• Searches standard library for file
• Use for standard library files
#include "filename"
• Searches current directory, then standard library
• Use for user-defined files
• Used for
– Loading header files (#include <iostream>)
– Programs with multiple source files to be compiled together
– Header file - has common declarations and definitions (classes, structures,
function prototypes)
• #include statement in each file
2000 Prentice Hall, Inc. All rights reserved.
13.3 The #define Preprocessor Directive:
Symbolic Constants
• #define
– Preprocessor directive used to create symbolic constants and macros.
• Symbolic constants
– When program compiled, all occurrences of symbolic constant replaced
with replacement text
• Format
#define identifier replacement-text
– Example: #define PI 3.14159
– everything to right of identifier replaces text
#define PI = 3.14159
• replaces "PI" with " = 3.14159", probably results in an error
– Cannot redefine symbolic constants with more #define statements
2000 Prentice Hall, Inc. All rights reserved.
13.4 The #define Preprocessor Directive:
Macros
• Macro
– Operation defined in #define
– Macro without arguments: treated like a symbolic constant
– Macro with arguments: arguments substituted for replacement text,
macro expanded
– Performs a text substitution - no data type checking
Example:
#define CIRCLE_AREA( x ) ( PI * ( x ) * ( x ) )
area = CIRCLE_AREA( 4 );
becomes
area = ( 3.14159 * ( 4 ) * ( 4 ) );
2000 Prentice Hall, Inc. All rights reserved.
13.4 The #define Preprocessor Directive:
Macros (II)
• Use parenthesis
– Without them:
#define CIRCLE_AREA( x ) PI * ( x ) * ( x )
area = CIRCLE_AREA( c + 2 );
becomes
area = 3.14159 * c + 2 * c + 2;
• Evaluates incorrectly
• Multiple arguments
#define RECTANGLE_AREA( x, y ) ( ( x ) * ( y ) )
rectArea = RECTANGLE_AREA( a + 4, b + 7 );
becomes
rectArea = ( ( a + 4 ) * ( b + 7 ) );
2000 Prentice Hall, Inc. All rights reserved.
13.4 The #define Preprocessor Directive:
Macros (III)
• #undef
– Undefines a symbolic constant or macro, which can later be
redefined
2000 Prentice Hall, Inc. All rights reserved.
13.5 Conditional Compilation
• Conditional compilation
– Control preprocessor directives and compilation
– Cast expressions, sizeof, enumeration constants cannot be
evaluated
• Structure similar to if
#if !defined( NULL )
#define NULL 0
#endif
– Determines if symbolic constant NULL defined
• If NULL is defined, defined(NULL) evaluates to 1
• If NULL not defined, defines NULL as 0
– Every #if ends with #endif
– #ifdef short for #if defined(name)
– #ifndef short for #if !defined(name)
2000 Prentice Hall, Inc. All rights reserved.
13.5 Conditional Compilation (II)
• Other statements
#elif - equivalent of else if in an if structure
#else - equivalent of else in an if structure
• "Comment out" code
– Cannot use /* ... */
– Use
#if 0
code commented out
#endif
to enable code, change 0 to 1
2000 Prentice Hall, Inc. All rights reserved.
13.5 Conditional Compilation (III)
• Debugging
#define DEBUG 1
#ifdef DEBUG
cerr << "Variable x = " << x << endl;
#endif
– Defining DEBUG enables code
– After code corrected, remove #define statement
– Debugging statements are now ignored
2000 Prentice Hall, Inc. All rights reserved.
13.6 The #error and #pragma Preprocessor
Directives
• #error tokens
– Tokens - sequences of characters separated by spaces
• "I like C++" has 3 tokens
– Prints message and tokens (depends on implementation)
– For example: when #error encountered, tokens displayed and
preprocessing stops (program does not compile)
• #pragma tokens
– Implementation defined action (consult compiler documentation)
– Pragmas not recognized by compiler are ignored
2000 Prentice Hall, Inc. All rights reserved.
13.7 The # and ## Operators
•#
– Replacement text token converted to string with quotes
#define HELLO( x ) cout << "Hello, " #x << endl;
HELLO(John) Notice #
becomes
cout << "Hello, " "John" << endl;
• Strings separated by whitespace are concatenated when using cout
• ##
– Concatenates two tokens
#define TOKENCONCAT( x, y ) x ## y
TOKENCONCAT( O, K )
becomes
OK
2000 Prentice Hall, Inc. All rights reserved.
13.8 Line Numbers
• #line
– renumbers subsequent code lines, starting with integer value
– file name can be included
• #line 100 "myFile.c"
– Lines are numbered from 100 beginning with next source code
file
– For purposes of errors, file name is "myfile.C"
– Makes errors more meaningful
– Line numbers do not appear in source file
2000 Prentice Hall, Inc. All rights reserved.
13.9 Predefined Symbolic Constants
• Five predefined symbolic constants
– Cannot be used in #define or #undef
Sym b o lic De sc rip tio n
c o n sta n t
__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 dd yyyy" such as "Jan 19 2001").
__TIME__ The time the source file is compiled (a string literal of the
form "hh:mm:ss").
2000 Prentice Hall, Inc. All rights reserved.
13.10 Assertions
• assert macro
– Header <assert.h>
– Tests value of an expression
– If 0 (false) prints error message and calls abort
assert( x <= 10 );
• If NDEBUG defined...
– All subsequent assert statements ignored
– #define NDEBUG
2000 Prentice Hall, Inc. All rights reserved.