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.
- Macro substitution
- File Inclusion
- 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:
- Simple macro substitution
- Arguemented macro substitution
- 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 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 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
#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__);
0 comments:
Post a Comment