What Is Preprocessor?
- Easy to read, easy to modify, more portable with more efficiency are imp issues
- The preprocessor processes the program before it passes to the compiler
- It operates under the control of directives
- They have different syntax rules!
- # Initially and no semicolon at the end!
Categories of Preprocessor Directives
- Macro substitution directives relates to replacing an identifier with predefined string or one or more tokens
- File inclusion directives relates to include a source file to current program
- Compiler control directives are for developing a single comprehensive program to suit different situations
Macro Substitution
- Is done under the control of #define
- It takes the general form #define id string
- Id must be any valid C name and the string may be any text
- Three diff forms of macro substitution are
- Simple macro substitution
- Argument macro substitution
- Nested macro substitution
Simple Macro Sub to Define Constants
Replacement starts from the line of definition
Macro inside a string does not get replaced
Simple Macro Sub for Expressions
#define AREA 5 * 12.46
#define SIZE sizeof(int) * 4
#define TWO-PI 2.0 * 3.1415596
#define D (45 – 22)
#define A (78 + 32)
- Expression like D/A should be (45-22)/(78 +32) and not 45 – 32/78 +32
- It performs a literal text sub so no ; is required
Simple Macro Sub for Creating C Sentences
- #define TEST if (x>y)
- #define AND
- #define PRINT printf(“Very Good\n”);
- We can now write TEST AND PRINT
- That will become
- if (x>y) printf (“Very Good\n”);
Simple Macro Sub for Replacing Tokens
#define EQALS ==
#define AND &&
#define OR ||
#define NOT-EQUAL !=
#define START {
#define END }
#define BLANK_LINE printf(“\n”);
#define INCREMENT ++
if (total EQUALS 240 AND average EQUALS 60) INCREMENT count;
Macros With Arguments
- More complex and more useful form of replacement
- #define identifier(f1,f2,…..,fn) string
- No space between id and the left (
- Subsequent occurrence of a macro with arguments is known as a macro call
- When macro is called, the preprocessor substitutes replacing formal with actual parameters
A Simple Example of Macros With Arguments (MWA)
#define CUBE(x) (x*x*x)
volume = CUBE (side) // (side * side * side)
volume = CUBE (a + b) would expand to
volume = (a + b * a + b * a + b)
So #define CUBE (x) ( (x) * (x) * (x) )is a correct definition, which expands to
volume = ((a +b) * (a + b) * (a + b))
Some Commonly Used Definitions
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define ABS(x) (((x) > 0) ? (x) : (-x))
#define STREQ(s1,s2) (strcmp((s1),(s2)) ==0)
#define STRGT(s1,s2) (strcmp((s1),(s2)) > 0)
#define PRINT(variable, format) printf (“variable = %format \n”, variable);
PRINT (price * quantity, f)
Nesting of Macros
#define M 5
#define N M + 1
#define SQUARE(x) ( (x) * (x) )
#define CUBE(x) ( (SQUARE(x)) * (x) ))
#define SIXTH(x) ((CUBE(x)) * (CUBE(x)))
The preprocessor expands each macro, until no macro appear in the text
Nesting of Macro, File Inclusion
#define HALF(x) ( (x) / 2.0)
#define ONE_4TH(x) (HALF(HALF(x)))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
MAX(a,MAX(b,MAX(c,d))) can be used to find out maximum of a, b, c, d
#undef <macro name>
#include “filename”
#include <filename>
Compiler Control Directives
- They are used for problems being faced while developing large programs
- They could be one of the following
- You have included a file containing macro definitions, how would you know that a particular macro is defined ?
- Suppose the customer has two different types of computers on which same program (that may have few diff lines in code) must run
- They are used for problems being faced while developing large programs
- They could be one of the following
- You have included a file containing macro definitions, how would you know that a particular macro is defined ?
- Suppose the customer has two different types of computers on which same program (that may have few diff lines in code) must run
Situation 1
- Using conditional compiling the problem can be solved
#define “DEFINE.H”
#ifndef TEST
#define TEST 1
#endif
- See that #define TEST 1 or #undef TEST could result into problems
Situation 2 or 3
Situation 4
#ifdef TEST
{ printf(“Array Elements\n”);
for (I=0;I<m;++I)
printf(“x[%d]=%d\n”); }
#endif
While debugging, we keep the TEST macro defined, when over, we undef it.
#if Directive
- #if constant expression
- { …….}
- #endif
- The constant expression can be any logical expression such as
- TEST <= 3
- (LEVEL == 1) || (LEVEL ==2)
- MACHINE == ‘A’
- #if defined -- New additions
- #if !defined -- New additions
ANSI Additions
- New preprocessor directives
- #elif for alternative test facility
- #pragma for specifying certain instructions to the compiler
- #error to stop compilation when error occurs
- New preprocessor operations
- # Stringizing operator
- ## Token pasting operator
#elif Directive
#if MACHINE == HCL
#define FILE “hcl.h”
#elif MACHINE == WIPRO
#define FILE “wipro.h”
#elif MCHINE == DCM
#define FILE “dcm.h”
#endif
#include FILE
Macros to Improve Portability, an Ex.
#if MACHINE = DOS
typedef size long int
typedef smallsize int
#elif MACHINE = UNIX || MACHINE = NT
typedef size int
typedef smallsize short int
#endif
Above code let the program to use size type variables to have 32 bit and smallsize type variables to have 16 bit irrespective of the machine type
Stringizing Operator #
- #define sum(x) printf(#x “=%f\n”,x)
- sum (a+b) will be expanded to
- printf(“a+b” “=%f\n”,a+b) which is equivalent to
- printf(“a+b=%f\n”,a+b)
- ANSI standard also stipulates that adjacent strings will be concatenated
Token Pasting Operator ##
- It helps us in combining two tokens within a macro definition to form a single token
#define combine(s1,s2) s1 ## s2
printf(“%f”,combine(total,sales));
printf (“%f”, totalsales)
#define print(I) printf(“a#I”= %f”,a##I)
print(5) will become
printf(“a5 = %f”,a5);