Preprocessors
Preprocessors is a program that modifies the C++ source
program according to directives supplied in the program. The original source
program is usually stored in a file. The preprocessors does not modify this
program file, but creates a new file that contains the processed version of the
program. This new file is then submitted to the compiler. The processor makes
the program easy to understand and port it form one platform to another. A
preprocessor carries out the following actions on the source file before it is
presented to the complier. These actions consists of
·
replacement of defined identifiers by pieces of
the text
·
conditional selection of parts of the source
file,
·
inclusion of other files, and
·
renumbering of source files and renaming of the
source files itself.
The general rules for defining a preprocessor are:
(a)
All preprocessors directives begin with the sharp sign
(#).
(b)
They must start in the first column and on most C++
compiler there can be no space between the number sign and the directive.
(c)
The preprocessors directive is terminated not by a
semicolon.
(d)
Only one preprocessor directive can occur in a line.
(e)
The preprocessors directives may appear at any place in
any source file: outside/inside functions or inside compound statements.
The C++ preprocessor
is a simple macro processor that conceptually processes the source text of a
C++ program before the compiler parses the source program. The preprocessor is
controlled by special preprocessor command lines, which are lines of the source
file beginning with the character’#’. Note that character ‘#’ has no other use
in the C++ language.
The Common C++
preprocessor directives and their uses are:
DIRECTIVE
|
USES
|
#include
#define
#undef
#if
#ifdef
#ifndef
#else
##elif
#endif
#line
#error
|
insert text from
another file
defined preprocessor
macro
remove macro
definitions
conditionally
include some text based on the value of the constant expression
conditionally
include some text based on predefined macro name
conditionally
include some text with the sense of the test opposite to that of#ifdef
alternatively
include some text, if the previous #if,#ifdef,or#ifndef tests failed
combination of #if
and #else
terminate
conditional text
give a line number
for compiler massages
terminate processing
early
|
4.11.1 Simple Macro Definitions
A macro is simply a substitution string that is placed in a
program.
For example , consider the following program segment,
#defined MAX 100
void main ( )
{
char name [MAX];
for ( i=0; i<= MAX-1; ++i)
}
which is internally replaced with the following program
void main ( )
{
char name [100]
for (i=0; i<= 100-1; ++i)
}
and subsequently compiled. Each occurrence of the identifier
MAX as a token is replaced with the
string 100 that follows the identifier
in the #defined line.
The simple from of
macro is particularly useful for introducing named constants into a program.
This makes it easier to change the number later.
For example, the
following are valid #defined statements.
#define TRUE 1
#define FALSE 0
#define EOF -1
#define SIZE 5
#define TRACK_SIZE 6
#define MAX_BLOCK 100
The syntax of the #define command does not require an equal
sign or any other special delimiter token after the name begin defined.
Some invalid #defined statements are illustrated below.
(1)
#define SIZE = 3
The #define statement is used to merely
substitute the string constants into the source program.
For example,
#define SIZE =3
#include <iostream.h>
void main ( )
{
int value [SIZE];
for (i=0; i<= SIZE-; ++i)
}
The macro substitutes every occurrence
of the SIZE with the =3, modifying the above source program as,
#include <iostream.h>
void main ( )
{
int value [=3]; // syntax error
for (i=0; i<= =3-1; ++i) // syntax error
}
(2) The #define statement does not take the semiclone.
#define MAX 100; //error
For example,
#define Max 100;
#include <iostream.h>
void main ( )
{
char name [MAX];
for (i = 0; I <= MAX-1; ++i)
}
The macro
substitutes every occurrence of the MAX with
the 100; modifying the above program
segment ,as,
#include <iostream.h>
void main ( )
{
char name [100;]; // syntax error
for (i =0; i <= 100;-1; ++ i) //
syntax error
}
Macro with Parameters
A more complex from of a macro definition declares the names
of formal parameters within parentheses, separated by commas.
#defined name (variable 1,variable2...variable
n) substitution_string
For example,
#define PRODUCT(x,y) ( (x) * (y) )
#define max (x,y) ((x) > (y) ? (x) :
(y))
#define min (x,y) ((x) < (y) ? (x) :
(y))
Macros operator purely by textual
substitution of tokens. The C++ compiler parses the source program only after
the completion of the macro expansion processes are completed. Hence, care must
be taken to get the desired result.
For example,
#define PRODUCT (x) x*x
If we call this macro definition in
the C++ program,
#define PRODUCT (x) x*x
void main ()
{
PRODUCT (10) ;
}
PRODUCT (10) expends 10*10. However, the expression
PRODUCT (a+1) expands to a+1*a+1
When the above
expression is executed, it is interpreted as
a+(1*a)+1 because the multiplication has higher precedence over the
addition. This will not produce the same result as (a+1) * (a+1) unless a
happens to be zero. It would be somewhat safer to put parentheses around
occurrences of the formal parameters in the definition of PRODUCT as,
#define PRODUCT (x) (x) *(x)
Even this
definition does not provide the complete protection against precedence
problems.
For example,
#define PRODUCT (x) (x)* (x)
#include <iostream.h>
void main ()
{
(short) PRODUCT ( a+1)
}
The preprocessor substitutes the
macro as
(short) (a+1) * (a+1)
then, it would be parsed as
((short) (a+1)) * (a+1)
as a cast has
higher precedence over multiplication. Hence proper parentheses should be used
within the macro definition statement to get the desired result. The correct
way of defining the PRODUCT macro is
#define
product (x) ((x) * (y))
Other Preprocessing Techniques
As the preprocessor merely substitutes a string of text for
another without any checking, a wide variety of substitutions are possible and
hence, it is possible to make any typed source program look like another
language. To illustrate the above, if someone has a strong linking for Pascal
and its syntax, then many Pascal symbols can be used in C++ symbols before the
compilation.
For example,
/* pascal.h */
#define begin
{
#define end
}
#define writeln
printf
#define mod
%
#define div /
#define program
main
#define integer
int
#define var /* variable declaration */
PROGRAM
A program define the Pascal syntax in a C++ program using a
macro declaration.
#include <stdio.h>
#include <pascal.h>
program ()
begin
writeln (“Pascal output|n” );
end
PROGRAM
A program to include the header file in a C++ program.
#include <stdio.h>
#include <pascal.h>
var
integer a,b,c;
program ()
begin
a + 10;
b + 20;
writeln ( “%d + %d = %d\n” ,a,b,c);
end
PROGRAM
A program for microprocessor simulator using the macro
definition.
#define SWAP (x,y,type)
{type temp; temp= (x) ; (x) = (y) =temp; }
#define MOV (d,s) (d) = (s);
#define ADD (d,s) (d) = (d) + (s);
#define MUL (d,s) (d) = (d)*(s); /* s – source */
#define DIV (d,s) (d) = (d) /(s); /* d –
destination */
#define XCHG (d,s) SWAP (d,s, SWAPTYPE);
#define OUT (value) printf (“%d”, (value));
#define OUTB (value) printf (“%c”, (value));
#define OUTS (label) printf (“%s”, (value));
#define LF
printf (“\n”);
#define ASCII (label, string) char *label +{ string};
#define WORLD (label) int label;
#define BYTE (label) char label;
#define START main () {
#define END
}
#define SWAPTYPE int
ASCII (msg, “Microprocessor simulator “)
START
WORLD (result)
WORD (r1)
WORD (r2)
MOV
( result ,0)
MOV
( r1 ,20)
MOV
( r2,20)
MOV
( result ,r1)
ADD
( result ,r2)
LE
OUTS
( “ Sum of = “)
OUT
( result)
LE
MOV
( result ,r1)
MUL
( result ,r2)
OUTS
( “Multiplication of =”);
OUT
(result )
LE
MOV
( result ,r1)
DIV
( result ,r2)
OUTS
( “Division of =”)
OUT ( result)
END
Conditional Compilation
The processor conditional compilation commands allow lines
of the source text to be passed through or eliminated by the preprocessor on
the basis of a computer condition.
The following are
the preprocessor conditional commands.
#if
#else
#endif
#elif
The above commands are used in the following way:
#if constant expression
group of lines 2
#else
group of lines 2
#endif
A group of lines may contain any
number of lines of the text or any kind, even other preprocessor command lines,
or no lines at all. The #else command
may be omitted.
The #elif command The #else command is fairly a recent addition to
C++. It is supported by very few compilers only. The #elif command is like a combination of #if and #else. It is
used between #if and #endif in the same way as #else but has a constant expression to
evaluate in the same way as #if.
It is used in the following format
#if
constant expression
group of lines 1
#elif constant expression
group of lines 2
#elif constant expression
group of lines 3
#else
group of lines n
#endif
The same commands can be written using #if, #else and #endif.
For example,
#if expression
#elif expression
#elif expression
#else
#endif
In case a part particular is not
supporting the #elif conditional command, Then the above commands may be
modified as:
#if expression
#else
#if expression
#else
#if expression
#else
#endif
#endif
#endif
No comments:
Post a Comment