C Preprocessors
The C Preprocessor is not a part of the compiler, but is a separate step in the compilation
process. In simple terms, a C Preprocessor is just a text substitution tool and it instructs the
compiler to do required pre-processing before the actual compilation. All preprocessor
commands begin with a hash symbol (#).
The preprocessor makes C code portable between different machine architectures &
customizes the language. The preprocessor performs textual substitutions on your source
code in three ways:
✓ File inclusion: Inserting the contents of another file into your source file. we write
#include which is a directive for the preprocessor that tells it to include the contents
of the library file specified. This can also be written using double quotes – #include
“stdio.h”
Note: If the filename is enclosed within angle brackets, the file is searched for in the
standard compiler include paths. If the filename is enclosed within double quotes, the
search path is expanded to include the current source directory.
✓ Macro substitution: Replacing instances of one piece of text with another. Macros can
be called as small functions that are not as overhead to process. If we have to write a
function (having a small definition) that needs to be called recursively (again and
again), then we should prefer a macro over a function. So, defining these macros is
done by preprocessor.
✓ Conditional compilation: Arranging that, depending on various circumstances, certain
parts of your source code are seen or not seen by the compiler at all.
#define for Constants
The syntax is as follows:
# define <literal> <replacement-value>
Note that no semicolon (;) need to be placed as the delimiter at the end of a # define line.
This is just one of the ways that the syntax of the preprocessor is different from the rest of C
statements (commands).
Examples:
#define MAX 100
The C preprocessor simply searches through the C code before it is compiled and
replaces every instance of MAX with 100.
#define PI 3.14
#define Stop }
#define Start {
We can remove already defined macros using #undef
Ex- #undef MAX
#define for functional Macros
#include <stdio.h>
# define SQR(x) (x*x)
void main()
{
int p,q;
printf("Enter any number to find its square: ");
scanf("%d", &p);
q = SQR(p);
printf("\n The square of %d is %d", p, q);
}
In this case, p is equated with x in the macro definition of square, so the variable q is assigned
the square of p. The expansion of the macro becomes:
q = (p* p);
other examples:
#define MAX(x,y) ((x) > (y) ? (x) : (y)) //for finding max number
#define swap(x, y) {int tmp = x; x = y; y = tmp; } //for swapping values
In particular, the textual substitution means that arithmetic expressions are liable to be
corrupted by the order of evaluation rules (precedence rules). You should be very careful in
using Macros. For example,
#define SQR(x) x*x
Now if we have a statement,
int P=3, Q;
Q=SQR(P+2);
It will be expanded like P+2*P+2 i.e. 3+2*3+2, therefore, Q=11 instead of 25.
The problem can be rectified using following code:
#define SQR(x) (x)*(x)
Macro for swapping
#include<stdio.h>
#define swap(t, x, y) { t tmp = x; x = y; y = tmp; }
void main( )
{
int a, b;
float p, q;
printf("enter integer values for a, b: ");
scanf("%d %d", &a, &b);
printf("\n Enter float values for p, q: ");
scanf("%f %f", &p, &q);
swap(int, a, b);
printf(" \n After swap the values of a and b are %d %d", a, b);
swap(float, p, q);
printf("\n After swap the values of p and q are %f %f", p, q);
}
The Macro Continuation (\) Operator: A macro is normally confined to a single line. The
macro continuation operator (\) is used to continue a macro that is too long for a single line.
#include <stdio.h>
# define TABLE(num) {int n;for(n=1;n<=10;n++) \
printf("\n%d*%d=%d",num,n,num*n);}
void main()
{
TABLE(5);
}
Macro Vs Functions
Macro calls are replaced with macro expansions (meaning). In function call, the control is
passed to a function definition along with arguments, and definition is processed and value
may be returned to call. Macros run programs faster but increase the program size. If macro
is called 100 numbers of times, the size of the program will increase. It is better to use Macros,
when the definition is very small in size. Macros are pre-processed while functions are
compiled. Also no type checking in case of macros.
C Predefined Macros
ANSI C defines many predefined macros that can be used in c program. These are identifiers
defined by the preprocessor, and cannot be undefined or redefined.
Macro Description
_DATE_ represents current date/date of compilation in "MMM DD YYYY" format.
_TIME_ represents current time in "HH:MM:SS" format.
_FILE_ represents current file name.
_LINE_ represents current line number.
_STDC_ It is defined as 1 when compiler complies with the ANSI standard.
#include<stdio.h>
int main(){
printf("File :%s\n", __FILE__ );
printf("Date :%s\n", __DATE__ );
printf("Time :%s\n", __TIME__ );
printf("Line :%d\n", __LINE__ );
printf("STDC :%d\n", __STDC__ );
return 0;
}
Conditional compilation
#ifdef : Returns true if this macro is defined. We can use this to skip certain codes or
to use specific set of code.
#ifndef : Returns true if the macro has not been defined.
#if, #else, #elif: enables us to establish an “if…else…if ..” sequence for testing multiple
conditions.
#endif : Ends preprocessor conditional.
Examples:
1. //demonstrate use of #if,#else and #endif
#include <stdio.h>
#define CHOICE 100
int my_int = 0;
#if (CHOICE == 100)
void set_my_int()
{
my_int = 1000;
}
#else
void set_my_int()
{
my_int = 5000;
}
#endif
main ()
{
set_my_int();
printf("%d\n", my_int);
}
2. //demonstrate use of #ifdef,#else and #endif
#include <stdio.h>
#define CHOICE 100
int my_int = 0;
#undef CHOICE
#ifdef CHOICE
void set_my_int()
{
my_int = 1000;
}
#else
void set_my_int()
{
my_int = 5000;
}
#endif
void main ()
{
set_my_int();
printf("%d\n", my_int);
}