C's Preprocessor
Tags: c, beginners
Published: 2019-12-25 13:09:49

We need not get terrified by the name __Preprocessor__.

If we go by the definition from __Wikipedia__ then "_The C preprocessor or cpp is the macro preprocessor for the C and C++ computer programming languages. The preprocessor provides the ability for the inclusion of header files, macro expansions, conditional compilation, and line control_". In simple words the Preprocessor is just like any other program which has a special task to process the programs written by us before it is compiled by the compiler. It basically
expands our program and converts the program file from a ".c" extension to a ".I" extension after it is done with the processing(expanding) of the program.

##Now the question arises what will the preprocessor expand??

We'll learn about that a bit later.

The preprocessor provides us with several features known as the "__Preprocessor Directives__".
It is these __Preprocessor Directives__ which get expanded by the Preprocessor.

Some of the __Preprocessor Directives__ are:-

##Macro expansion
This directive solves one of our most basic problems. Consider the following code snippet.

    main()
    {
        for(i=0;i<25;i++)
        {
            for(j=0;j<25;j++)
            {
                printf("%d", i);
            }
        }
    }

Now for example if we want both the loops in the above program to execute till i and j are less than 30 and not 25, we would then have to go to both the places and change 25 to 30.
And what if there were ten loops in the main function and what if there were 2 more funtions. It would then be a tiring task. 
It is for this that we have Macro expansions. Now consider the following code snippet with using macro expansions.
 
    #define LIMIT 25
    main()
    {
        for(i=0;i<LIMIT;i++)
        {
            for(j=0;j<LIMIT;j++)
            {
                printf("%d", i);
            }
        }
    }

In the above program you would observe something new and that is "#define LIMIT 25".
This new line is known as a macro definition and LIMIT is known as macro template and 25 is known as macro expansion. Now if we want to change 25 to 30 then all that we had to do was to change 25 to 30 in the very first line of the program. And this change would be applicable for the other functions where LIMIT has been used.
Now when the preprocessor processes the program file it replaces every LIMIT occurrence with 25.
Macros can also be used to define functions. For example:

    #define PRT(X,Y){\
                          printf("%d %d",X,Y);\
	                }\

In the above example "\" is used so that the Preprocessor may know that the macro expansion is of multiple lines.
Macro expansion have a disadvantage. Although they make the program run faster but they increase the size of the program. Functions make the program smaller and compact. If we use macro in our program at a hundred places then when the Preprocessor processes the program it will put macro expansion at all those hundred places thus increasing the size of the expanded source file. But in case of functions it will be called a hundred times. Passing the parameters in case of functions a hundred times and evaluating the function all those times makes the program run slower, whereas in case Macro expansion since it has already being processed by the Preprocessor it will only be evaluated once.

##File Inclusion
What if we are working on a big project. It would then be difficult to manage all the functionalities because the project file would be very big. So, we divide the project into many smaller files, which contains functions that control a particular task. This is where we need the help of "#include" directive. This directive is used to merge two or more files. When we include a particular program file or header file in a program then when the Preprocessesor processes the program it simply copies all the content of that file in the file being processed. Therefore it gets converted into one single file.Consider the following code snippet:

    #include<hello.c>
    main()
    {
        print("Using a function from another file");
        fun();
    }

In the above program as you see that there is no function defined as fun() but still this program will execute without any errors, because a function fun() has already been defined in the file "hello.c". When the Preprocessor processes the above program it simply copies all the contents of the file "hello.c" in the above program therefore it is able to access the function fun().
In addition to adding other program files we also add header files in our program. Header files are predefined programs which contain frequently used functions that we may include in our program.
Files are included in a program using the include directive in two ways:
<p>#include <filename>  OR  #include "filename"</p>

##Conditional Compilation
This directive can be very helpful in some situations like what if we had to skip over some part of the program. Yes, I know what you are thinking that this can also be done using comments. But what if that part of the program which we want to skip already has comments in it?? This is where conditional compilation comes into play. The syntax for this directive is as follows:

    #ifdef macro name
    statement 1;
    statement 2;
    statement 3;
    #else
    statement 4;
    statement 5;
    statement 6;
    #endif

The above statements will only be executed if the macro name is defined. We also have another option an alternative:

    #ifndef macro name
    statement 1;
    statement 2;
    statement 3;
    #else
    statement 4;
    statement 5;
    statement 6;
    #endif

The above statements will only be executed if the macro name has not being defined earlier.

##Miscellaneous Directives

###undef Directive

If we want to undefine some name then we use this directive. 

    #undef PENTIUM

The above statement would cause the definition of PENTIUM to be removed from the system.

###pragma Directive

The functions that are specified with the "#pragma startup " directive are called before the main function executed, and the functions that are specified with the "#pragma end " directive are called before the program terminates.
We also have another pragma directive "pragma warn ". It tells the compiler whether or not we want to suppress a warning.

    #pragma warn -rvl
    #pragma warn -par
    #pragma warn -rch

The above three statements would suppress the warnings for return value, parameter not used and unreachable code.

In this post I tried to explain a concept of C language, that is mostly overlooked, in as simple way as possible.