Conditional Preprocess Directives


In C programming language, conditional preprocessing directives are used to control which code is included in a program during compilation. These directives are processed by the preprocessor, which is a program that runs before the compiler and modifies the source code.

Conditional Preprocessor Directives

There may be situations when we want to compile some parts of the code based on some condition. We know that before compilation the source code passes through the preprocessor. So we can direct the preprocessor to supply only some parts of the code to the compiler for compilation.

  • Conditional compilation means the compilation of a part of code based on some condition.
  • These conditions are checked during the preprocessing phase.
  • The directives used in the conditional compilation are-
#ifdef
#ifndef
#if
#else
#elif
#endif

The #ifdef, #ifndef, and #endif directives in C are used for conditional compilation. The #ifdef directive tests whether a particular macro has been defined using the #define directive.

The #if, #elif, #else, and #endif directives in C are used for conditional compilation based on the value of an expression.

Every #if directive should end with a #endif directive. The working of these directives is somewhat similar to that of the if... else construct.

#if And #endif

The #if directive tests whether a specified expression evaluates to true, and if it does, the code following #if is compiled. If the expression is false, the code following #if is ignored and not compiled.

Here's their syntax :

         #if constant-expression
      // code to be compiled 
     // if the constant expression is true
 #endif        
    

The #endif directive is used to mark the end of the conditional block of code.

These directives are commonly used in conjunction with preprocessor macros and constants to selectively compile code based on certain conditions.

The constant expression should be an integral expression and it should not contain an enum constant, sizeof operator, cast operator, or any keyword or variables. It can contain arithmetic,' logical, and relation operators.

If any undefined identifier appears in the expression, it is treated as having the value zero.

For example, you might use #if and #endif to include or exclude debugging code from the final build of a program.

        #include <stdio.h>#define DEBUG 1
int main() {
  #if DEBUG
    printf("Debugging information: x = %d, y = %d\n", x, y);
  #endif
  // rest of the code
  return 0;
}            

In this example, the code inside the #if block will only be compiled if the macro DEBUG is defined and evaluates to a non-zero value.

#if and #else

#else is used with the #if preprocessor directive. It is analogous to if.., else control structure.

The Syntax :

        #if constant-expression
    statements
#else
    statements
#endif            

If the constant expression evaluates to non-zero then the statements between #if and #else are compiled otherwise the statements between #else and #endif is compiled.

        #include <stdio.h>
#define MAX_VALUE 100

int main() {
    int num = 50;

#if MAX_VALUE > 50
    printf("MAX_VALUE is greater than 50.\n");
#else
    printf("MAX_VALUE is not greater than 50.\n");
#endiff
    return 0;
}            

In this program, we first define the macro MAX_VALUE to be 100. We then use #if to conditionally compile the first printf statement based on whether MAX_VALUE is greater than 50.

If it is, the statement is compiled, and if not, the #else branch is compiled instead.

#if, #elif and #else

#if, #else, and #elif are used to conditionally compile code based on certain conditions.

The Syntax :

        #if constant-expression
    statements
#elif
 statements
#else
    statements
#endif        
    

If the constant expression evaluates to non-zero then the statements between #if ,and #elif are compiled otherwise the statements between #else and #endif is compiled.

        #include <stdio.h>int main() {
    int num = 50;
#if defined(_WIN32)
    printf("This is a Windows system.\n");
#elif defined(__linux__)
    printf("This is a Linux system.\n");
#else
    printf("This is not a Windows or Linux system.\n");
#endif

#if num > 100
    printf("num is greater than 100.\n");
#elif num > 50
    printf("num is greater than 50 but less than or equal to 100.\n");
#else
    printf("num is less than or equal to 50.\n");
#endif

    return 0;
}            

We use #if and #elif to conditionally compile the second printf statement based on whether the _WIN32 or __linux__ macros are defined. If neither is defined, the #else branch is compiled.

Finally, we use #if, #elif, and #else to conditionally compile the third printf statement based on the value of the num variable. If num is greater than 100, the first branch is compiled.

If it is greater than 50 but less than or equal to 100, the second branch is compiled. If it is less than or equal to 50, the #else branch is compiled.

#ifdef and #ifndef

#ifdef and #ifndef are preprocessor directives in C and C++ that are used for conditional compilation, which allows developers to include or exclude code from the final executable based on certain conditions.

The directives #ifdef and #ifndef provide an alternative short form for combining #if with the defined operator.

#if defined(macro_name ) is equivalent to #ifdef macro_name
#if !defined(macro_name ) is equivalent to #ifndef macro_name

Syntax of #ifdef -

#ifdef macro name
.................
#endif

If the macro_name has been defined with the #define directive, then the statements between #ifdef and #endif will be compiled.

If the macro_name has not been defined or was undefined using #undef, these statements are not compiled.

Syntax of #ifndef -

#ifndef macro_name
.....................
#endif

If the macro_name has not been defined using #define or was undefined using #undef, then the statements between #ifndef and #endif are compiled.

If the macro_name has been defined, then these statements are not compiled.

Let us take a program-

#include <stdio.h>#define TEST

int main() {

#ifdef TEST
    printf("The macro TEST is defined!\n");
#endif

#ifndef TEST2
    printf("The macro TEST2 is not defined!\n");
#endif

    return 0;
}

In this example, the macro TEST is defined using #define, so the code within the #ifdef block will be compiled and the output will be: "The macro TEST is defined!".

#ifndef, on the other hand, tests whether a particular macro is not defined. If the macro is not defined, the code within the #ifndef block will be compiled, otherwise, it will be skipped.

Here is an example -

#include <stdio.h>//#define TEST

int main() {

#ifdef TEST
    printf("The macro TEST is defined!\n");
#endif

#ifndef TEST2
    printf("The macro TEST2 is not defined!\n");
#endif

    return 0;
}

In this example, the macro TEST is commented out using //, so it is not defined.

The code within the #ifndef block will be compiled, and the output will be: "The macro TEST is not defined!" and "The macro TEST2 is not defined!".

If we uncomment the #define TEST line, the output will be only "The macro TEST2 is not defined!".

defined Operator

This operator is used only with #if and #elif directives. It evaluates to 1 if the macro_name has been defined using #define, otherwise, it evaluates to zero. For example:

#if defined(FLAG)

Syntax :

defined(macro_name )

If the macro FLAG has been defined using #define, then the value of the expression defined(FLAG) would be 1, otherwise, its value would be 0.

The existence of a defined operator is important in some cases. For example, we can't use the short forms(#ifdef and #ifndef) here) -

1. When we need to check the existence of more than one macro, for example

#if defined(ABC) && defined(PQR) && !defined(XYZ)

2. When the existence of macro is to be checked in #elif

#if defined (ABC)
...............
#elif defined ( PQR)
...............
#elif defined(XYZ)
...............
#endif

There are a lot of situations where conditional compilation can prove useful e.g. writing portable code, debugging, and commenting.

Loading...

Search