# PREPROCESSORS
Overview :
Programming
c is a very interesting language. To make it more attractive and little bit
easy we have some directives, that we can use in our c program. Preprocessors
are very important topic in c. It is also very important for freshers attending interviews. As its name suggest Preprocessor
is a program that processes our source program before it is passed to the
compiler.
Do you
know how our c program compiles and generate output or executable file??
There
are few steps like preprocessor, compiler, assembler, linker and loader.
ex.
gcc options.....
If our
c file name is test.c and
we want to see how our file looks like after preprocessor stage, we can compile
our program by using “gcc -E test.c”(“gcc”
is used in linux). After this we will get new file with extension “.i “ ,so in our case it will be test.i .
gcc options.....
preprocess - E generates .i
compiler - s generates .s
Assembler - c
linker - o generates .o
loader - o
Preprocessor :
What is Preprocessor ?
The
preprocessor offers several features called preprocessor directives. Each of
these preprocessor directives begin with a # symbol. The directives can be
placed anywhere in a program but are most often placed at the beginning of a
program, before the first function definition.
Types Of Preprocessor :
There
are four different types of preprocessors.
1. macro expansion
2.
file inclusion
3.
conditional compilation
4.
Miscellaneous directives.
We will see this one by one.
How to use Preprocessor ?
1. MACRO EXPANSION :
#define
PI 3.14
void main(void)
{
int r,ans;
r=2;
ans = 2*PI*r;
printf(“ans
= %d\n”,ans);
}
In this
program instead of writing 3.14 we are writing PI. Here PI is already been
defined before main(). Now suppose we are using value 3.14 around 15 to 20 times
in our program. And after writing full program we get to know that value should
be 3.1426. so we have to find each 3.14 in our program and replace it with
3.1426. So if you don’t want to spend your time for this, you can declare it as Macro (#define PI 3.14) and can use PI everywhere in your program instead of
3.14. and when you want to replace 3.14 with 3.1426 you have to make only one change
(#define PI 3.1426).
Here
PI is not a variable but it is a constant. Macro doesn't get any kind of memory space in system like variables because before compilation in preprocessor stage it will be replaced by its value everywhere in program.
Note:
If you are using linux, copy this program (name test.c), compile it with gcc –E test.c. you will get test.i file and cat
test.i you will find your program changed to :
#define
PI 3.14
void main(void)
{
int r,ans;
r=2;
ans = 2*3.14*r; //see
changes here -> 3.14 instead of PI.
printf(“ans
= %d\n”,ans);
}
Another
use…
#define
SENTENCE printf(“hello world!!!\n”) //Note that Macros must be in all capital letters.
void main(void)
{
int
i=0;
if
( i == 0)
SENTENCE;
else
printf(“Error!!”);
}
Run
this and see the magic.
Here
SENTENCE will be replaced with whole sentence
“ printf(“hello world!!!\n”) ”.
So program
will print “hello world!!!”.
Another
use…
#define AREA(x,y) ( x * y )
void main(void)
{
int val1 = 6, val2 = 2, a;
a = AREA (val1, val2) ;
printf
( "\nArea of rectangle = %d", a ) ;
val1 = 5;
val2 = 3;
a = AREA ( val1,val2) ;
printf
( "\nArea of rectangle = %d", a ) ;
}
Here’s the output of the
program...
Area of rectangle = 12
Area
of rectangle = 15
In this program wherever the preprocessor
finds the phrase AREA(x,y) it expands it into the statement ( x
* y ). However, that’s not all what it does. The x and y in the macro
template AREA(x,y) are an argument that matches the x and y in the macro
expansion ( x * y ). The statement AREA(val1, val2) in the program
causes the variable to be substituted for x and y. Thus the
statement AREA(val1, val2) is equivalent to: ( val1 * val2 ).
Now you will have question, where to use function and where to use macro ???
Macro vs Function
Interviewer generally ask this question to the freshers.
So here is the pros and cons:
1.
macro -> increases the size of program.
1. function->size
doesn't increase.
2.
macro -> increases the speed of
execution. // doesn't need calling
and returning.
2.
function-> not as fast as macro.
3.
macro -> when macro becomes large it's good to use function. Because program
becomes
lengthy.
3.
function-> when macro is large good idea to use function. // it saves memory.
2. FILE INCLUSION :
This
is very simple pre-processor to understand.
It's
nothing but #include<stdio.h>
and many more header files that we can include at the start of program.
I
am not going in more details for this.
3. CONDITIONAL COMPILATION :
Just like if, else if and else here we have some conditional compilation
directives like ifdef, endif, elif.
#ifdef macroname
statement 1 ;
statement 2 ;
statement 3 ;
#endif
We
can include this lines before main or in main.
Here
if given macroname is defined with #define , given statement will be executed
otherwise will not.
#ifdef
is used when you like to compile only a part of your program
main( )
{
#ifdef INTEL
statement 1 ;
statement 2 ;
statement 3 ;
statement 4 ;
#endif
#ifdef
ARM
statement 5 ;
statement 6 ;
statement 7 ;
#endif
statement 8 ;
statement 9 ;
statement 10 ;
}
Suppose you are going to make software which has some code only for intel
processor based PC, some code only for ARM based PC. And remaining is common
for both.
Then
if your processor is intel then statement 1-4 & 8-10 will be
visible for that software code.
To
make this code compatible for ARM based PC you have to just remove definition of
intel and add definition of ARM.
For
example, remove #define INTEL and
write #define ARM.
So
we changed only one line and now your software code will be compatible with
ARM. That’s the power of preprocessor.
4. MISCELLANEOUS DIRECTIVES :
These directives are rarely used.
1. #undef
2. #pragma
1. #undef
We used #define, ex. #define INTEL.
And now if we want to undefined intel then we can
remove that line or we can use #undef
INTEL.
2. #pragma
Sometime interviewers ask…what is pragma
directive?
There are some predefined pragma directives like
#pragma startup and #pragma exit.
void fun1( ) ;
void fun2( ) ;
#pragma startup fun1
#pragma exit fun2
main( )
{
printf ( "\nInside main" ) ;
}
void fun1( )
{
printf ( "\nInside fun1" ) ;
}
void fun2( )
{
printf ( "\nInside fun2" ) ;
}
O/P:
Inside func1
Inside main
Inside func2
Till now in C we studied that execution of our
program always start with main.
But by using pragma we can break this rule. So pragma
tells compiler to do some task as suggested by him.
#pragma warn:
This directive tells the
compiler whether or not we want to suppress a specific warning. Usage of this
pragma is shown below.
#pragma warn –rvl /*
return value */
#pragma warn –par /*
parameter not used */
#pragma warn –rch /*
unreachable code */
int f1( )
{
int a = 5 ;
}
void f2 ( int x )
{
printf ( "\nInside f2" ) ;
}
int f3( )
{
int x = 6 ;
return x ;
x++ ;
}
void main( )
{
f1( ) ;
f2 ( 7 ) ;
f3( ) ;
}
Here in f1() we declare “ int a
” but never used and it returns nothing, in f2() we are passing 7 to x but
never used, in f3() execution will never reach to x++. So these all are warnings a compiler will show, but when you will compile this program you will not get
any warnings. Why???
Because of the pragma
directives which we have defined at the start of program. It will suppress all such
warnings.
So that’s all about Preprocessor.
--------------------------------------------------------------------------------------------------------
To know more about another important topic in c “POINTER”
visit : http://letsmakeceasy.blogspot.in/2014/09/pointer-in-c.htmlTo know more about another important topic in c “POINTER”
Are you a Fresh Programmer?? Join facebook group to be a perfect programmer.
https://www.facebook.com/groups/121611948548929/
https://www.facebook.com/groups/121611948548929/
Thanks,
Akash Patel
No comments:
Post a Comment