<Previous Lesson

Visual Programming

Next Lesson>

Lesson#5

Preprocessor Directives

Preprocessor.....................................................................................................2
Preprocessor directives: #ifdef and #ifndef ....................................................2
Prevent multiple definitions in header files.....................................................2
Turning debugging code off and on ...............................................................2
Some Preprocessor directives...........................................................................3
#define....................................................................................................3
Example: macro #defines ..............................................................................3
#error ......................................................................................................3
#include ..................................................................................................3
Conditional Compilation - #if, #else, #elif, and #endif........................................4
#ifdef and #ifndef ....................................................................................4
#undef.....................................................................................................4
#line........................................................................................................4
#pragma .................................................................................................4
The # and ## Preprocessor Operators ..............................................................5
Macros ..............................................................................................................5
Standard Predefined Macros .........................................................................5
__FILE__................................................................................................6
__LINE__................................................................................................6
__DATE__..............................................................................................6
__TIME__...............................................................................................6
__STDC__..............................................................................................6
__STDC_VERSION__............................................................................7
__STDC_HOSTED__.............................................................................7
__cplusplus.............................................................................................7
Summary...........................................................................................................7
Tips ...................................................................................................................7
Preprocessor Directives 2

Preprocessor

The preprocessor is a program that runs prior to compilation and potentially modifies a
source code file. It may add code in response to the #include directive, conditionally
include code in response to #if, #ifdef, #ifndef directives or define constants using the
#define directive.
As defined by the ANSI standard, the C preprocessor contains the following directives:
#if #ifdef #ifndef #else #elif #include #define #undef #line #error #pragma

Preprocessor directives: #ifdef and #ifndef

The #ifdef (if defined) and #ifndef (if not defined) preprocessor commands are used to
test if a preprocessor variable has been "defined".

Prevent multiple definitions in header files

When there are definitions in a header file that can not be made twice, the code below
should be used. A header file may be included twice because more than one other
“include file” includes it, or an included file includes it and the source file includes it
again.
To prevent bad effects from a double include, it is common to surround the body in the
include file with the following:

#ifndef MYHEADERFILE_H
#define MYHEADERFILE_H

. . .
// This will be seen by the compiler only once
#endif /* MYHEADERFILE_H */
Turning debugging code off and on
Debugging code is necessary in programs; however, it is not usually appropriate to leave
it in the delivered code. The preprocessor #ifdef command can surround the debugging
code. If DEBUG is defined as below (probably in an include file) all debugging statement
surrounded by the #ifdef DEBUG statement will be active. However, if it isn't defined,
none of the statements will make it through the preprocessor.

#define DEBUG
. . .
#ifdef DEBUG

. . . // debugging output

#endif

Preprocessor Directives
3

Some Preprocessor directives

#define

#define defines an identifier (the macro name) and a string (the macro substitution) which
will be substituted for the identifier each time the identifier is encountered in the source
file. Once a macro name has been defined, it may be used as part of the definition of
other macro names.
If the string is longer than one line, it may be continued by placing a backslash on the end
of the first line. By convention, C programmers use uppercase for defined identifiers.

Example: macro #defines

#define TRUE 1
#define FALSE 0
The macro name may have arguments, in which case every time the macro name is
encountered; the arguments associated with it are replaced by the actual arguments found
in the program, as in:

#define ABS(a) (a)<0 ? -(a) : (a)
...
printf("abs of -1 and 1: %d %d", ABS(-1), ABS(1));

Such macro substitutions in place of real functions increase the speed of the code at the
price of increased program size.
#error

#error forces the compiler to stop compilation. It is used primarily for debugging. The
general form is:

#error error_message

When the directive is encountered, the error message is displayed, possibly along with
other information (depending on the compiler).
#include

#include instructs the compiler to read another source file, which must be included
between double quotes or angle brackets. Examples are:

#include "stdio.h"
#include <stdio.h>

Both of these directives instruct the compiler to read and compile the named header file.
If a file name is enclosed in angle brackets, the file is searched for as specified by the
creator of the compiler. If the name is enclosed in double quotes, the file is searched for
Preprocessor Directives 4
in an implementation-defined manner, which generally means searching the current
directory. (If the file is not found, the search is repeated as if the name had been enclosed
in angle brackets.)

Conditional Compilation - #if, #else, #elif, and
#endif

Several directives control the selective compilation of portions of the program code, viz,
#if, #else, #elif, and #endif.
The general form of #if is:

#if constant_expression

statement sequence

#endif

#else works much like the C keyword else. #elif means "else if" and establishes an ifelse-
if compilation chain.
Amongst other things, #if provides an alternative method of "commenting out" code. For
example, in

#if 0
printf("#d",total);
#endif

the compiler will ignore printf("#d",total);.
#ifdef and #ifndef

#ifdef means "if defined", and is terminated by an #endif. #ifndef means "if not defined".
#undef

#undef removes a previously defined definition.
#line

line changes the contents of __LINE__ (which contains the line number of the currently
compiled code) and __FILE__ (which is a string which contains the name of the source
file being compiled), both of which are predefined identifiers in the compiler.
#pragma

The #pragma directive is an implementation-defined directive which allows various
instructions to be given to the compiler i.e. it allows a directive to be defined.
The #pragma directive is the method specified by the C standard for providing additional
information to the compiler, beyond what is conveyed in the language itself. Three forms
of this directive (commonly known as pragmas) are specified by the 1999 C standard. A
C compiler is free to attach any meaning it likes to other pragmas.
Preprocessor Directives 5

The # and ## Preprocessor Operators

The # and ## preprocessor operators are used when using a macro #define. The #
operator turns the argument it precedes into a quoted string. For example, given:

#define mkstr(s) # s

the preprocessor turns the line

printf(mkstr(I like C);

into

printf("I like C");

The ## operator concatenates two tokens. For example, given
:
#define concat(a, b) a ## b
int xy=10;
printf("%d",concat(x, y);
the preprocessor turns the last line into:
printf("%d", xy);
Macros
A macro is a fragment of code which has been given a name. Whenever the name is used,
it is replaced by the contents of the macro. There are two kinds of macros. They differ
mostly in what they look like when they are used. Object-like macros resemble data
objects when used, function-like macros resemble function calls.
You may define any valid identifier as a macro, even if it is a C keyword. The
preprocessor does not know anything about keywords. This can be useful if you wish to
hide a keyword such as const from an older compiler that does not understand it.
However, the preprocessor operator defined can never be defined as a macro, and C++'s
named operators cannot be macros when you are compiling C++.
To define a macro that takes arguments, you use the #define command with a list of
parameters in parentheses after the name of the macro. The parameters may be any valid
C identifiers separated by commas at the top level (that is, commas that aren't within
parentheses) and, optionally, by white-space characters. The left parenthesis must follow
the macro name immediately, with no space in between.
For example, here's a macro that computes the maximum of two numeric values:
#define min(X, Y) ((X)>(Y) ? (X):(Y))
Standard Predefined Macros
The standard predefined macros are specified by the C and/or C++ language standards, so
they are available with all compilers that implement those standards. Older compilers
may not provide all of them. Their names all start with double underscores.
Preprocessor Directives 6
__FILE__

This macro expands to the name of the current input file, in the form of a C string
constant. This is the path by which the preprocessor opened the file, not the short names
specified in #include or as the input file name argument. For example,
"/usr/local/include/myheader.h" is a possible expansion of this macro.
__LINE__

This macro expands to the current input line number, in the form of a decimal integer
constant. While we call it a predefined macro, it's a pretty strange macro, since its
"definition" changes with each new line of source code.
__FILE__ and __LINE__ are useful in generating an error message to report an inconsistency
detected by the program; the message can state the source line at which the inconsistency
was detected. For example,
fprintf (stderr, "Internal error: "
"negative string length "
"%d at %s, line %d.",
length, __FILE__, __LINE__);
An #include directive changes the expansions of __FILE__ and __LINE__ to correspond to
the included file. At the end of that file, when processing resumes on the input file that
contained the #include directive, the expansions of __FILE__ and __LINE__ revert to the values
they had before the #include (but __LINE__ is then incremented by one as processing moves
to the line after the #include).
__DATE__

This macro expands to a string constant that describes the date on which the preprocessor
is being run. The string constant contains eleven characters and looks like "Feb 12 1996".
If the day of the month is less than 10, it is padded with a space on the left.
__TIME__

This macro expands to a string constant that describes the time at which the preprocessor
is being run. The string constant contains eight characters and looks like "23:59:01".
__STDC__

In normal operation, this macro expands to the constant 1, to signify that this compiler
conforms to ISO Standard C.
Preprocessor Directives 7
__STDC_VERSION__

This macro expands to the C Standard's version number, a long integer constant of the
form yyyymmL where yyyy and mm are the year and month of the Standard version.
This signifies which version of the C Standard the compiler conforms to.
This macro is not defined if the -traditional option is used, nor when compiling C++ or
Objective-C.
__STDC_HOSTED__

This macro is defined, with value 1, if the compiler's target is a hosted environment. A
hosted environment has the complete facilities of the standard C available.
__cplusplus

This macro is defined when the C++ compiler is in use. You can use __cplusplus to test
whether a header is compiled by a C compiler or a C++ compiler. This macro is similar
to __STDC_VERSION__, in
that it expands to a version number.

Tips

Do use the preprocessor directives as much as possible in your programme as it
makes the programme more robust.
Preprocessor Directives 8
Using the #defined, #ifndef directives helps in Prevent multiple definitions in
header files.
Conditional compilation with the use of preprocessor directives provides a very
easy way for turning the debug code on and off.
A macro is a fragment of code which has been given a name. Whenever the name
is used, it is replaced by the contents of the macro.
Macros can be used for writing clear and easily comprehensible code.
Do remember that whenever the macro name is used, it is replaced by the contents
of the macro.

Summary

The preprocessor is a program that runs prior to compilation and potentially modifies a
source code file. It may add code in response to the #include directive, conditionally
include code in response to #if, #ifdef, #ifndef directives or define constants using the
#define directive.
A simple macro is a kind of abbreviation. It is a name which stands for a fragment of
code. Some standard pre-defined Macros include __FILE__, __LINE__, __DATE__,

__TIME__ etc.

<Previous Lesson

Visual Programming

Next Lesson>

Home

Lesson Plan

Topics

Go to Top

Next Lesson
Previous Lesson
Lesson Plan
Topics
Home
Go to Top