Monday, August 11, 2014

The C – Preprocessor

The C – Preprocessor


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

The syntax of preprocessor directives begin with the symbol # and donot 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 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:
  1. Simple macro substitution
  2. Arguemented macro substitution
  3. Nested macro substitution

A simple macro:


A simple macro is generally used to define symbolic constants.
example:
#define PI 3.14159
#define TRUE 1
#define CITY “Kathmandu”
#define TWO_PI 2*(22/7)
#define BLANK_LINE printf(“\n”);
#define INCREMENT ++
#define START {
#define END } etc.
The Uppercase letter for IDENTIFIER is conventions for defining Constants.

Arguemented macro :

We can define complex macro with arguments. The syntax is
#define IDENTIFIER(a1,a2,…..,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 )
Example:
#define SQUARE(x) ((x)*(x))
#define CUBE(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)); /*substitution of macro */
Other examples of arguemented macro:
#define MAX(a,b) (((a)>(b))? (a): (b))
#define MIN(a,b) (((a)<(b))? (a) : (b))
#define MODVAL(x) (((x)>0) ? (x) : (-(x)))
#define RECIPROCAL(x) (1.0/(x)) etc.

Nesting macro:


We can use one pre-defined macro to define new macro. This is called nesting of macro definition.
Example:
#define PI 3.14159
#define TWO_PI 2*PI
#define SQUARE(x) ((x)*(x))
#define CUBE(x) ((x)*SQUARE(x))
#define SIX_POWER(x) ((CUBE(x))*(CUBE(x)))
  • Given the definition of macro MAX(a,b) , We can use nested call of macro to fine maximum of three numbers a,b,c as:
MAX(a,MAX(a,b))
  • To define multiple lines we can use \ character at the end of each line:
Undifining a Macro:


A defined macro can be undefined , using the statement:
#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 #include directive. If we include pre-written file in our source program we need not to 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<filename> is used, the file inside < > is searched in the standard directory and included in the source program where it is written. If file is not find 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 file is not find 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(“\nThe square of %d is %d” , x, square(x));
printf(“\nThe cube of %d is %d “, x, cube(x));
printf(“\n The 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)


Conditional compilation enables the programmer to control the execution of preprocessor directive and the compilation of the program code. Each of the conditional preprocessor directive evaluates a conatant integer expression.
The conditional preprocessor directive construct is similar to if-else construct. The conditional compilation can be done using #if, #elif ,#else, #ifdef ,#ifndef.
Examples:
#if defined(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 expression is non-zero, subsequent lines until #endif are included.

For multiple selection of lines to include, #elif, #else can be used as else if and else in selection structures. Suppose there is different versions of header file for different systems. To decide which version of a header file to include, we can write preprocessor directive as:

#if SYSTEM == SYSV
#define HDR “sysv.h”
#elif SYSTEM == BSD
#define HDR “bsc.h”
#elif SYSTEM == MSDOS
#define HDR “msdos.h”
#else
#define HDR “default.h”
#endif

#include HDR

Some Pre defined macros



ANSI C has five pre defined macros. These macros can not be undefined or redefined by programmer . Each of these macros name include two leading and two trailing underscore ‘_’ characters.
1. __DATE__ A string containing the current date of the form “Mmm dd yyyy”
2. __TIME__ A string containing the current time of the form “hh:mm:ss”
3. __LINE__ The line number of the current source code line
4. __FILE__ The file name of the current source file
5.__STDC__ If implementation follows ANSI standard of C then value is non zero.


Try the following Code in your program:
printf(“\n__DATE__ = %s”, __DATE__);
printf(“\n__TIME__ = %s”, __TIME__);
printf(“\n__LINE__ = %s”,__LINE__);
printf(“\n__FILE__ = %s”, __FILE__);
printf(“\n__STDC__ = %s”,__STDC__);



HackerBoy

Compiled By Sabin Khanal

0 comments:

Post a Comment

 

Copyright @ 2013 Learn Programming.

Designed by Templateiy & CollegeTalks