C Preprocessors

This is one of the special features available in C, but not found in many other languages. The preprocessor is a part of the C-compilation process that recognizes special statements (that may be found anywhere in the program) and takes appropriate action(s). The programmer can use these special statements to make his program easier to read and modify, customize or write easily transportable programs. Each preprocessor statement is identified by a # sign, which must be the first character of the line.

We shall briefly see some of the preprocessor statements and their uses. The define statements: This is one of the most popularly used C preprocessor statements, with multiple users. The format I something like this:

#define TRUE 1
#define false 0

(note that there is no semicolon after the statement)

Once this is done, throughout the program, you can use True wherever constant 1 is to be used and false where 0 is to be used. Note that they can be used only as constants and not variables. For example, we can not add 1 to True etc. All that the preprocessor does is to scan through the program and replace True with 1 and false with 0, so that the C compiler can understand them.

You may ask why it is needed at all. Quite often, we need to make decisions based on whether something is true or false. Unlike other languages (like Pascal, for ex.) C does not have Boolean variables that can be set to true or false. In such a case, the programmer has to artificially remember to replace true with 1 and false as 0 (or any other combination for that matter) and write the program. This may lead to confusion or mistakes. Thus by defining them in the beginning and then writing the program in the way we think. We will be able to write better programs. We see an example to classify the simulation.

#define TRUE 1
#define FALSE 0
/* Function to determine if an integer is even */
int is_even (number)
int number;
{
 int answer;
 if (number % 2 = = 0)
    answer = TRUE;
 else
    answer = FALSE;
       return(answer);
}

Output:

NO YES

Now, going back to the format, we specifically insisted that no semicolon should be there after define. This is because the preprocessor blindly replaces the True value with 1 and false with 0. Suppose we have written.

# define True 1 ;

Then in the place where the statement answer = True; appears, True gets replaced by 1; so the compiler sees a statement answer = 1;; which is invalid. Hence no semicolons should appear in define.

i) Program extentability: suppose you have written a program that has something to do with 1000 students. So, your array is of the size 1000, these may be a number of for loops that terminate at 1000, etc. now after some time, the number of students increases to 1500. Then wherever 1000 appears, you have to change it to 1500. This is easier said than done. You are bound to miss some commit errors etc. An easier method is to simply define no of students as 1000.

# no_of_students 1000

and wherever 100 is to be used to indicate the students, use the constant no_of_students like for:

(i=0;i<no_of_students;++i)

Whenever the number of students changes, we can change only the define statement and not throughout the program.

ii) Program Portability: Certain parameters are machine dependent, like the maximum integer you can store etc. when you go from a 16 bit machine to a 32 bit machine or viceversa, you have to change them. Instead, you can use a define statement like

#define wordlength 16

and when you go through a 32-bit machine, simply change the statement.

Simple Functions: Define need not always be simple numbers. It can be pointers or even simple equalians consider:

#define square(s) x*x

This would same almost as a library function and whenever we write say y = square(z), it gets replaced to y = z*z. Consider one more interesting case. You have to check whether a particular year is a leap year and then take some decisions. Then, wherever we have to check for leap year, we should write if (year%4 == 0) && (year%100!=0 || year % 400 == 0).

Instead at one place, write

# define leap_year ((year%4 == 0) && (year%100!=0 \
         || year % 400 == 0))

and use if(leap_year) in the program (incidentally the \ is used whenever the define exceeds one line.)

Since define statements can be used as definitions, they are often called “macros”, a form used for expandible assembly language functions.

The # include statement

If you keep writing a large number of C programs, you realize that certain define functions are needed again and again. Instead of writing them in define functions in every program, you can collect all of them in a file and include that file in the program.

Now you can have a clear concept of # include files we were using for input/output functions. Only things stdio.h, math.h, etc. files are provided by the system. But you can also write your won files and include them using the include statement.