Preprocessor Directives C

  • Macro expansion
  • File inclusion
  • Conditional compilation
  • Miscellaneous directives

Preprocessor directives can be categorized into four types. Macro expansion, file inclusion, conditional compilation and miscellaneous directives. We have used the #include directive in our examples. It falls into the category of file inclusion directive.

Macro expansion

  • Simple macros.
  • Macro with arguments.
  • Why use macros?

There can be two types of macros one which has no arguments; they are called as simple macros and one which takes arguments. Arguments are values passed to the macros so that the same macro can be used over a wide range of values. Later on we will also discuss how macros are useful.

  1. Simple macro
    The definition has the following form
    #define name replacement text

    name = it is called the macro template.
    replacement text = it is called the macro expansion.
    The rules for giving a macro name are same as for variable name. Generally macro name is written
    with capital letters.E.g.

    Simple macro

    The program is first passed to the preprocessor where it sees if macros are present. It replaces all occurrences of UPPER in the program with 25. Substitutions are only done for separate whole names, not names within double quotes or if name is part of another name. i.e. replacement won’t take place for “UPPER” or UPPERCASE..

  2. Macro with arguments
    Macros can also be used with argument so that we can obtain different replacement text for different values of arguments.

    Here all occurrences of AREA are replaced by the replacement text.i.e.
    a = AREA (r1) is replaced by
    a = (3 * r1 * r1), x is replaced by r1 and also
    a = AREA (r2) is replaced by
    a = (3 * r2 * r2), X is replaced by r2.

    No blank should be left between the macro template and its argument. The entire macro expansion should be enclosed in brackets.

  3. Why use macros?
    If relevant and suitable names are given then macros are used to increase the readability. Secondly, more important thing is if we decide to change 25 to 40 in our example and if we don’t use macro, we will have to change 25 to 40 at all places in the program. When macro is used, change has to be made at only one place.

    UPPER is also called as symbolic constant, since value 25 remains constant throughout the program
    Other example of simple macros can be

    #define directive is used to replace a ‘C’ statement.
    #defines FOREVER for (: :)
    #define FOUND printf (“The Yankee Doodle Virus”)
    #define is used to replace a operator and a condition
    #define AND &&
    #define ARRANGE (a>25 AND a<50)

    The macro expansion can also contain a macro template.

File inclusion
We have used
#include directive in programs written so far
#include filename
The contents of the file given by filename are replaced at the point where the directive is written. If we have written number of function for specific purpose and if we write programs that use them, then declarations of these functions, macros used, declaration of external variable can all be combined in the header file. Instead of repeating the above-mentioned statement in each program that uses them, we can include the header file in our programs using the file inclusion directive.

The header file stdio.h supplied with ‘C’ contains function declarations and all the information regarding input and output. Hence when we use I/O function in our programs we include this header file.

The file inclusion statement can be written in two ways

If we use the first way, ‘C’ would search for the file; filename in the current working directory as well
as in the specified list of directories.
If we use the second way, the file; filename will be searched only in the specified list of directories.

Conditional compilation
A number of the directives control conditional compilation, which allows certain portions of a program to be selectively compiled or ignored depending upon specified conditions. The directives concerned are: #if, #ifdef, #ifndef together with the preprocessor unary operator defined.

The way that they are used is like this:

The #else can be used with #ifdef (and #if or #elif) too. There is no ambiguity about what a given #else binds to, because the use of #endif to delimit the scope of these directives eliminates any possible ambiguity. The Standard specifies that at least eight levels of nesting of conditional directives must be supported, but in practice there is not likely to be any real limit. These directives are most commonly used to select small fragments of C that are machine specific (when it is not possible to make the whole program completely machine independent), or sometimes to select different algorithms depending on the need to make trade-offs.

The #if and #elif constructs take a single integral constant expression as their arguments. Preprocessor integral constant expressions are the same as other integral constant expressions except that they must not contain cast operators. The token sequence that makes up the constant expression undergoes macro replacement, except that names prefixed by defined are not expanded. In this context, the expression defined NAME or defined ( NAME ) evaluates to 1 if NAME is currently defined, 0 if it is not. Any other identifiers in the expression including those that are C keywords are replaced with the value 0. Then the expression is evaluated. The replacement even of keywords means that sizeof() can't be used in these expressions to get the result that you would normally expect.

if , #elif, #else, #endif
#ifdef, #ifndef

We can select whether certain lines of code are to be compiled or not using the conditional compilation directives.

#if, #elif, #else, #endif

The if directive test the expression following it and depending upon the result of the expression decides whether to compile statements.

If we have number of conditions to check, instead of using #else or #if number of times we can use #elif if we want to compile code depending upon the adapter used in our machine.

Thus certain code can be compiled only if macro HDR is defined. We will require such a macro if for example we are not sure that code has to be deleted or may be required at some later time. Don’t define HDR and write the above conditional directive for your code. It won’t be compiled. Later if you become sure that you don’t need the statements, you delete them. If you need them remove the #ifdef directive or define the macro HDR.

Compiles statement following it upto #endif if HDR is not defined

Miscellaneous directives

  • #undef
  • #pragma

We have few more directives, which do not fit in the above categories, hence described separately. #udef is the directive which is used in relation to the #define directive and #pragma is the directive which is just introduced here since it is a specialized directive, used very rarely.

  1. #undef
    In order to undefined a defined macro we can use the #undef directive.
    #undef macro name
    if we have defined
    #define UPPER 25
    at some place in the program, we can remove it from the system by using
    #undef UPPER
  2. E.g.
  3. #pragma
    These are special purpose directives that you can use to turn on or off certain features.
    There are different pragmas for different compilers. Turbo C compiler has got a pragma, which allows us to write assembly language statements in ‘C’ program.

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd Protection Status

C Topics