Preprocessor directives in c

By | May 19, 2019

C preprocessor:

The preprocessor is the program that processes the source code before it passes through the compiler. It operates under the control of the preprocessor command line or directives. Preprocessor directives are defined in the source program before the mainline written the source code passes through the compiler, it is examined by the preprocessor. After taking appropriate actions as directed by the preprocessor, the source program is handed over to the compiler.

The syntax of preprocessor directives begin with the symbol # and don’t require semi colon (;) at the end. The preprocessor directives can be divided into three
categories.

  1. Macro substitution
  2. File Inclusion
  3. Compiler control Directives

1. Macro substitution

In macro substitution, an IDENTIFIER is replaced by pre-defined string. The
preprocessor accomplishes this job under the direction of #define directives which is called the macro. The syntax for macro definition is:

define IDENTIFIER string

If this line is included at the beginning of the program, preprocessor replaces IDENTIFIER in source code by string defined in macro. The IDENTIFIER must be C valid name.
There are three different forms of macro substitutions:
a. Simple macro substitution
b. Arguemented macro substitution
c. Nested macro substitution

A Simple macro:

A simple macro is generally used to define symbolic constants.

eg:
#define PI 3.1415
#define TRUE 1
#define CITY “KATHMANDU”
etc.

the uppercase letter for the identifier is conventions for defining constant

Arguemented macro:

We can define complex macro with arguments. The syntax is

#define IDENTIFIER(a1,a2,a3…..an) string

  • There is no space between IDENTIFIER and parenthesis.
  • a1,a2….an are macro formal parameters.
  • when a macro is called, the preprocessor substitutes the string, replacing the formal parameters with actual parameters(passed when calling macro)

eg:

#define SQUARE(x) ((x)*(x))

#define CUBB(x) ((x)*(x)*(x))

we can call these macro in our source program as

Area=PI*SQUARE(radius);

which is equivalent to

Area= PI((radius)*(radius));

Nesting macro:

we can use one pre-defined macro to define new macro. This is called nesting of macro definition.

eg:
#define PI 3.1415
#define TWO_PI 2*PI
#define SQUARE(x) ((x)*(x))
#define CUBE(x) ((x)*SQUARE(x))

given the definition of macro MAX(a,b) we can use nested call of macro to find a maximum of three numbers a,b,c as:
MAX(a,MAX(a,b))

to define multiple lines we can use the character at the end of each line:

Undifining a Macro:

The defined macro can be easily undefined, using the statement below:

#undef IDENTIFIER

It is useful when to restrict the definition only to a particular part of the program.

2. File inclusion directives: (#include directives)

A file which contains the pre-defined macros and functions can be included in our source program using the #include directive. If we include pre-written file in our source program we need not rewrite the functions and macro which are defined in that file. The syntax for file inclusion directive is :

#include<filename> or #include “filename”

  • When #include is used, the file inside < > is searched in the standard directory and included in the source program where it is written. If the file is not found an error is reported.
  • When #include “filename” is used, the file inside “ ” is searched first in the current directory and then standard directory included in the source program where it is written If the file is not found an error is reported.

A simple example of file inclusion:

Consider a file named test.c which includes the definition of functions for square and cube and macro to find the maximum of two numbers, and constant PI.

/* test.c*/
#define PI 3.14
#define MAX(x,y) (((x>(y))?(x) : (y))
int square(int x) /*square function*/
{
return x*x;
}
int cube(int x) /*cube function */
{
return (x*x*x);
}
Now we have to write a program that uses functions and macros defined in test.c the source program is as:
/*source.c*/
#include<stdio.h>
#include “test.c”
void main()
{
int x=10, y=20;
printf(“\n square of %d is %d”, x, square(x));
printf(“\n cube of %d”, x, cube(x));
printf(“\n larger no is %d “, MAX(a,b);
}

when we run the source file source.c the output will be

The square of 10 is 100
The cube of 10 is 1000
The larger no is 20

3. Compiler control directives(Conditional Compilation)

The Conditional compilation enables a programmer to control the execution of the preprocessor directive and also the compilation of the program code. Every conditional preprocessor directives evaluate a constant integer expression.
The conditional preprocessor directive construct is similar to the if-else construct.The conditional compilation can be done using #if, #elif ,#else, #ifdef ,#ifndef.

Example:
#if define (NULL)
#undef NULL
#endif
This can be equivalently defined as:
#ifdef NULL
#undef NULL
#endif

This conditional directives search for the definition of NULL in the current header file and source file if it is defined then it is undefined.
similarly:
#if !defined(NULL)
#define NULL 0
#endif
or equivalently,
#ifndef NULL
#define NULL 0
#endif

This conditional directives search for the definition of NULL in the current header file and source file if it is not defined then it is defined to 0. In the above directives, if line evaluates the constant integer expression. If an expression is non-zero, subsequent lines until #endif are included.






Leave a Reply

Your email address will not be published. Required fields are marked *