Programming in C: Unit I (d): Preprocessor Directives

Conditional Directives

with Example C Programs | Preprocessor Directives

A conditional directive is used to instruct the preprocessor to select whether or not to include a chunk of code in the final token stream passed to the compiler.

CONDITIONAL DIRECTIVES

A conditional directive is used to instruct the preprocessor to select whether or not to include a chunk of code in the final token stream passed to the compiler. The preprocessor conditional directives can test arithmetic expressions, or whether a name is defined as a macro, etc.

Although the conditional preprocessor directive resembles an if statement, it is important to understand the difference between them. The condition in an if statement is tested when the program is executed. So the same c program may behave differently from run to run, depending on the data it is operating on. However, the condition in a preprocessing conditional directive is tested when the program is being compiled. This facilitates the programmer to allow different code to be included in the program depending on the situation at compile time.

However, in today's scenario the distinction is becoming less clear. Modern compilers usually test if statements during program compilation in order to check if their conditions are known not to vary at run time, and vary at eliminate code which can never be executed. If you have such a modern compiler then the use of an if statement is recommended as the program becomes more readable if you use if statements with constant conditions.

Conditional preprocessor directives can be used in the following situations:

• A program may need to use different code depending on the machine or operating system it is to run on. This may be because in certain situations, the code for one operating system becomes erroneous on another operating system. For example, the program might refer to data types or constants that do not exist on the other system. When this happens, it is not enough to avoid executing the invalid code; as even the presence of such data types and constants will make the compiler reject the program. Therefore, in such situations the conditional preprocessing primitive is effective as with preprocessor the offending code can be effectively exercised from the program when it is not valid.

• The conditional preprocessor directive is very useful when you want to compile the same source file into two different programs. While one program might make frequent time-consuming consistency checks on its intermediate data, or print the values of those data for debugging, the other program, on the other hand can avoid such checks.

• The conditional preprocessor directives can be used to exclude code from the program whose condition is always false but is needed to keep it as a sort of comment for future reference.

#ifdef

#ifdef is the simplest sort of conditional preprocessor directive and is used to check for the existence of macro definitions. Its syntax can be given as

#ifdef MACRO

controlled text

#endif

This block is called a conditional group. The controlled text will be included in the output of the preprocessor if and only if MACRO is defined. The #ifdef is said to be successful if the MACRO is defined. The controlled text will be executed only if the #ifdef succeeds.

Even if the #ifdef directive fails, the controlled text inside it is still run through initial transformations and tokenization. So, the programmer must ensure that the controlled text is lexically valid. For example, all comments and string literals inside a failing conditional group must still end properly.

Note

The kind of optimization done by the operating system at each level is beyond the scop As the statements under the controlled text of the #ifdefe of this book. directive are not enclosed in braces, the #endif directive must be used to mark the end of the #ifdef block.

The following example defines a stack array if MAX is defined for the preprocessor.

#ifdef MAX

int STACK [MAX];

#endif

In the above example, the stack array will not be created if MAX had not been initially defined.

#ifndef

The #ifndef directive is the opposite of #ifdef directive. It checks whether the MACRO has not been defined or if its definition has been removed with #undef. #ifndef is successful and returns a non-zero value if the MACRO has not been defined. Otherwise in case of failure, that is when the MACRO has already been defined, #ifndef returns false (0

Therefore, #ifndef directive is used to define code that is to be executed when a particular macro name is not defined. The general format to use #ifndef is the same as for #ifdef:

#ifndef MACRO

controlled text

#endif

Here, MACRO and controlled text have the same meanings as they have in case of #ifdef. Again, the #endif directive is needed to mark the end of the #ifndef block.

You can also use #else directive with #ifdef and #ifndef directives like

#ifdef MACRO

controlled text1

#else

controlled_text2

#endif

#if Directive

The #if directive is used to control the compilation of portions of a source file. If the specified condition (after the #if) has a non-zero value, the controlled text immediately following the #if directive is retained in the translation unit.

The #if directive in its simplest form consists of

#if condition

controlled text

#endif

In the above syntax, condition is a C expression of integer type, subject to stringent restrictions, i.e., the condition may contain the following:

• Integer constants (which are all treated as either long or unsigned long).

• Character constants

• Arithmetic operators for addition, subtraction, multiplication, division, bitwise operations, shifts, comparisons, and logical operations.

• If an identifier used in the expression is not a macro and has not been currently defined, the compiler treats the identifier as though it were the constant zero.

• Macros which are actually expanded before computation of the expression's value begins.

• Defined operator can be used.

• The sizeof operator is not allowed in #if directives.

• Type cast operator is not allowed.

• Enumerated data types are not allowed.

• The condition must not perform any environmental inquiries and must remain insulated from implementation details on the target computer.

• Increment, decrement, and address operator are not allowed.

The controlled text inside the directive can include other preprocessing directives. However, any statement or any preprocessor directive in the controlled text will be executed if that branch of the conditional statement succeeds.

While using #if directive in your program, make sure that each #if directive must be matched by a closing #endif directive. Any number of #elif directives can appear between the #if and #endif directives, but at most one #else directive is allowed. However, the #else directive (if present) must be the last directive before #endif.

#else Directive

The #else directive can be used within the controlled text of a #if directive to provide alternative text to be used if the condition is false. The general format of #else directive can be given as

# if condition

Controlled text1

#else

Controlled text2

#endif

If condition evaluates to a non-zero value then controlled text1 becomes active and the #else directive acts like a failing conditional and the controlled text2 is ignored. On similar grounds, if the condition fails or evaluates to zero, then controlled text2 is considered included and controlled text1 is ignored.

The #else directive is usually used to delimit alternative source text to be compiled if the condition tested for in the corresponding #if, #ifdef, or #ifndef directive is false. However, a #else directive is optional.

#elif Directive

The #elif directive is used when there are more than two possible alternatives. The #elif directive like the #else directive is embedded within the #if directive and has the following syntax:

#if condition

Controlled text1

#elif new_condition

Controlled text2

#else

Controlled text3

#endif

Here, when the if condition is non-zero then controlled text1 becomes active and the #elif and #else directives act like a failing conditional and the controlled text2 and controlled text3 are ignored. On similar grounds, if the condition fails or evaluates to zero, then new_condition is evaluated. If it is true, controlled text 2 is considered included and controlled text1 and controlled text3 are ignored. Otherwise, if condition and new_condition both are false then #else directive becomes active and controlled text3 is included.

The #elif directive is same as the combined use of the else-if statements. The #elif directive is used to delimit alternative source lines to be compiled if condition in the corresponding #if, #ifdef, #ifndef, or another #elif directive is false and if the new_condition in the #elif line is true, an #elif directive is optional.

#define MAX 10

#if OPTION==1

int STACK [MAX];

#elif OPTION== 2

float STACK [MAX];

#elif OPTION== 3

char STACK [MAX];

#else

printf("\n INVALID OPTION");

#endif

Note

The #elif does not require a matching' #endif' of its own. Every #elif directive includes a condition to be tested. The text following the #elif is processed only if the #if condition fails and the #elif condition succeeds.

In the above example, we have used more than one #elif directives in the same #if-#endif group. The text after each #elif is processed only if the #elif condition succeeds after the original #if and any previous #elif directives within it have failed,

Note

If the condition specified with #if directive is false and if either no #elif directives appear or no #elif condition evaluated to true, then the preprocessor selects the text block after the #else clause. If the #else directive is also missing then no controlled text is selected.

#endif Directive

The general syntax of #endif preprocessor directive which is used to end the conditional compilation directive can be given as

#endif

The #endif directive ends the scope of the #if, #ifdef, #ifndef, #else, or #elif directives. The number of #endif directives that is required depends on whether the elif or #else directive is used. For example, consider the examples given below which although perform the same task, requires different number of #endif directives.

#if condition

Controlled text1

#elif new_condition

Controlled text2

#endif

OR

#if condition

Controlled text1

#else

#if new_condition

Controlled text2

#endif

#endif

Programming in C: Unit I (d): Preprocessor Directives : Tag: : with Example C Programs | Preprocessor Directives - Conditional Directives