Check The Programming Section
If we want, we can instruct the C compiler to skip a part of source code foe compilation and executing by inserting the preprocessor directives #ifdef and #endif, which have the general form:
#ifdef MACRONAME
statement1;
statement2;
#endif
If macro name is #defined then the block of code written in between #ifdef and #endif will be executed else ignored by the compiler. Let us see where we can use conditional preprocessor directives.
To "comment out" obsolute line of code. Sometimes we need to satisfy the requirement of the client with a last minute modification of the code. In this case, we normaly comment out the old code by inserting it in between #ifdef and #endif and write the required code, as follows:
#ifdef MACRONAME
OLD_CODE
#endif
NEW_CODE
You might think, we can do same thing by putting the block of code inside the block commenting using /* ...... */. Now think, that code you want to comment out is already uses the block comment, the C programming does not allow nesting of comments, as follows:
/*
statement1;/* */
statement2;
*/
But experienced programmers are familiar with the clients who change their mind and want the old code back again just the way it was. Now you would definitely not like to retype the deleted code again. The solution to use conditional compilation is as follows:
#ifdef OLDCODE
statement1;
statement2;
statement3;
#endif
So, when we need to ignore the OLDCODE then the definition for macro OLDCODE is ignored else definition is required.
The more sophisticated use of #ifdef is to make to code portable which makes the code to execute into two different computers. To do this we need to use another conditional preprocessor directives #else. The code written after the #ifdef will execute for one computer after satisfying the system requirements and the code written after the #else will be executed for second computer. For example,
#include<stdio.h>
#define INTEL
int main(){
int k;
#ifdef INTEL
k = 89;
#else
k = 90;
#endif
printf("%d",k);
}
In the above example, the macro name INTEL is defined and in this case statement written after #ifdef get executed and the value k is set to 89. If we want to execute the second version (#else) then, we need to remove the macro definition and the value of k is set to 90. As follows
#include<stdio.h>
int main(){
int k;
#ifdef INTEL
k = 89;
#else
k = 90;
#endif
printf("%d",k);
}
Sometimes instead of #ifdef the preprocessor directives #ifndef (means if not defined) is used. It is just worked the opposite of #ifdef and if the macro is not defined then the code segment written after #ifndef get executed, otherwise #else. For example,
#include<stdio.h>
int main(){
int k;
#ifndef INTEL
k = 10;
#else
k = 20;
#endif
printf("%d",k);
}
In the above code instead of #ifdef, #ifndef is used and the macro PRINT is not defined in the code. So the code segment written after #ifndef get processed and the value of k is set to 10.
Another important use of #ifndef, #endif preprocessor directives to provide an #include guard sometimes called macro guard, header guard or file guard is a particular construct used to avoid the problem of double inclusion when dealing with the include directive. The C preprocessor processes the #include <file> by locating the file in hard drive and includes its contents tnto a copy of source file known as the transplation unit, replacing the include directive in the process. It is quite possible if we include a file twice in a C project then the content of that header file will be copied multiple times and the resulting translation can make invalid. Consider the example,
Source Code of the "first.h"
/*first.h*/
#include<stdio.h>
void fun1(){
printf("From first.h\n");
}
Source Code of the "second.h"
#include"first.h"
void fun2(){
fun1();
printf("From second\n");
}
Source Code of the "main.c"
#include "second.h"
#include "first.h"
int main() {
fun2();
fun1();
return 0;
}
If all these three file is part of one C project, then first.h header file is included twice in the project. At first in the second.h header file and at last main.c file. While compiling the project the copies of first.h is added twice and it maeks the linking of the object file become fail. So to stop being copied the first.h two times to the object code of the project the source code of the first.h can be put in between the #ifndef and #endif preprocessor directives. See the example,
/*first.h*/
#include<stdio.h>
#ifndef __first_h
#define __first_h
void fun1(){
printf("From first.h\n");
}
#endif
/*second.h*/
#include"first.h"
#ifndef __second_h
#define __second_h
void fun2(){
fun1();
printf("From second\n");
}
#endif
/*main.c*/
#include "second.h"
#include "first.h"
int main() {
fun2();
fun1();
return 0;
}
First time the file first.h gets included the preprocessor checks whether a macro called __first_h has been defined or not. If it has not been then it gets defined and the rest of the code gets included. Next time we attempt to include the same file, the inclusion is prevented since __first_h already stands defined. Note that there is nothing special about __first_h. In its place we can use any other macro as well.