Preprocessing

PREPROCESSOR

Introduction

C's preprocessor provides a facility for defining constant and substitution, which are commonly called macros. It is used when you either want the make to program more readable or when you don't have enough information about certain values. For example, if your input is in U.S. dollars, and your processing is done in terms of rupees, then your program may have the expression

Rs = usd * 46;

where 46 is the currency rate. You can write the expression as:

# define currency_rate 46 rs = usd * currency_rate;

So, if the currency rate is changed, you can make the necessary change only in one place. The preprocessor directive is defined here.

Program

# include #define VAL 35 // A #define HELLO "HELLO"; // B main () { int res; res = VAL-5; // C printf ("res = VAL-5: res == %d ", res); printf ( HELLO); //D }

Statements A and B indicate preprocessor directives. VAL is defined as integer 35 and HELLO is a string as "HELLO". Whenever VAL and HELLO appear, they are replaced by the specified values.

In statement C, VAL 35 is replaced by VAL −5. So the statement becomes

res = 35-5;

Statement D, after replacement, becomes

printf ("HELLO")

The preprocessor directives are not C statements, so they do not end with semicolons.

The include directive tells the compiler to include all the contents of a specified file in the source file before giving the source file for compiling.

Explanation

  1. The preprocessor substitutes strings that are specified by using define directive

    #define constant identifer "value"

  2. Following are valid define expressions:

    #define TRUE 1 #define FALSE 0 #define BS '' #define TAB '11'

undef

Introduction

If you want to nullify the effect of the define directive and specify a new value, then you can use the undef directive.

Program

#include #define VAL 40; //A #undef VAL //B #define VAL 40 //C main() { printf ("%d ", VAL); //D }

Explanation

  1. Statement A defines VAL as 40, that is, an erroneous definition.
  2. Statement B indicates that the afore mentioned definition no longer exists.
  3. Statement C allows a new definition.
  4. Statement D uses new definition of 40.

Point to Remember

The undef directive nullifies the effect of an earlier definition.

ifdef

Introduction

The ifdef directive makes substitutions based on whether a particular identifier is defined.

Program

Suppose we have three files:

file1.h #define USD 1 file2.h #define UKP 1 file3 #include #include //A #ifdef USD // B #define currency_rate 46 //C #endif //D #ifdef UKP // E #define currency_rate 100 //F #endif //G main() { int rs; rs = 10 * currency_rate; //H printf ("%d ", rs); }

Explanation

  1. Statement A includes file1.h, so the content of the file is substituted in that position. If the file name is given in angle brackets, it means the file is searched in the default search path. If the file name is specified within “”, like include "file1.h", then file1.h is searched only in the current directory.
  2. Statement B is an ifdef directive and it checks whether the identifier USD is defined. Since it is defined in file1.h, the condition is true and the currency rate is defined as 46. You can include multiple directives in if, def and endif.
  3. Statement E checks whether the identifier UKP is defined. Since it is not defined, because file2.h, is not included in the file, the condition is false and its defined directive is not processed.
  4. The currency rate in file3 is taken as 46.
  5. In the expression in statement H, the currency rate is substituted as 46.
  6. If, instead of file1.h, you include file2.h, then the currency rate will be 100.

Points to Remember

  1. ifdef is used to make a substitution depending on whether a certain identifier is defined.
  2. If the identifier is defined, it returns true; otherwise, it is false.

ifndef

Introduction

#ifndef is used to check whether a particular symbol is defined.

Program

Suppose wse have three files:

file1.h #define USD 1 file2.h #define UKP 1 file3 #include #include //A #ifndef USD // B #define currency_rate 100 //C #endif //D #ifndef UKP // E #define currency_rate 46 //F #endif //G main() { int rs; rs = 10 * currency_rate; //H printf ("%d ", rs); }

Explanation

  1. ifndef is a complement of ifdef. That is, if the symbol is defined, ifndef returns false.
  2. Statement B is an ifndef directive and it checks whether the identifier USD is defined. Since it is defined in file1.h, the condition is false and further processing is not done.
  3. Statement E checks whether the identifier UKP is defined. Since it is not defined, because file2.h is not included in the file, the condition is true and the currency rate is defined as 46.
  4. The currency rate in file3 is taken as 46.
  5. In the expression in statement H, the currency rate is substituted as 46.
  6. If, instead of file1, you include file2.h, then the currency rate will be 100.
  7. ifndef is a complement of ifdef. So, when ifdef returns true, ifndef returns false.

#if

Introduction

#if allows you to define more generalized conditions. Multiple conditions, which are connected by relational operators such as AND(&&), OR(||), are allowed.

Program

Suppose we have three files:

file1.h #define USD 1 file2.h #define UKP 1 file3 #include #include //A #if ((1>0) &&(defined (USD)) // B #define currency_rate 46 //C #endif //D #if (defined (UKP)) // E #define currency_rate 100 //F #endif //G main() { int rs; rs = 10 * currency_rate; //H printf ("%d ", rs); }

Explanation

  1. Statement B indicates the if directive.
  2. The generalized form of the if directive is

    #if #endif

  3. The condition (1>0) is absolutely not necessary here. It is given just to indicate how you can concatanate multiple conditions.
  4. The condition defined (USD) is true only if the identifier USD is defined.
  5. Since file1.h is included and USD gets defined, the condition is evaluated as true and the currency rate is defined as 46.
  6. In statement E, the condition is false because UKP is not defined.
  7. In the statement H, the currency rate is 46.

Points to Remember

  1. The if directive allows us to use a condition more generalized than ifdef.
  2. The defined() predicate returns true if the symbol is defined; otherwise, it is false.

ifelse

Introduction

The ifelse directive lets us specify the action if the condition is not true.

Program

Suppose we have three files:

file1.h #define USD 1 file2.h #define UKP 1 file3 #include #include //A #if (defined (USD)) // B #define currency_rate 46 #else #define currency_rate 100 //C #endif //D main() { int rs; rs = 10 * currency_rate; //H printf ("%d ", rs); }

Explanation

  1. Statement B indicates the ifelse directive.
  2. If the identifier USD is defined, the currency rate is taken as 46; otherwise, the currency rate is taken as 100.
  3. Since USD is defined in file1.h, the currency rate is taken as 46.

Point to Remember

The ifelse directive allows us to take action if the condition is not satisfied.

ifelif

Introduction

ifelif allows us to take one action if there are multiple decision points. For example, if you want to take the currency rate of 1 if USD and UKP are not defined, you can write the following program.

Program

Suppose we have three files:

file1.h #define USD 1 file2.h #define UKP 1 file3 #include #include //A #if (defined (USD)) // B #define currency_rate 46 #elif (defined (UKP)) #define currency_rate 100 //C #else # define currency_rate 1 //D #endif main() { int rs; rs = 10 * currency_rate; //H printf ("%d ", rs); }

Explanation

  1. Statement B includes the ifelif directive. It is similar to the else directive.
  2. #elif appears only after #if, #ifdef, #ifndef, and #elif.
  3. #elif is similar to #else but it is followed by a condition.
  4. You can have as many #elif directives as you want.
  5. If USD is defined, then the currency rate is 46; otherwise, if UKP is defined, then the currency rate is 100; otherwise, the currency rate is 1.
  6. In this case, if you remove the statement include file1.h at position A, then USD and UKP are not defined and currency rate is taken as 1.

Points to Remember

  1. #elif is similar to #else but it is followed by a condition.
  2. #elif allows taking action in the case of multiple decision points.

ERROR DIRECTIVE

Introduction

The error directive is used to specify an error message for a specific situation. In the following program, the error message is displayed if USD and UKP are not defined.

Program

Suppose we have three files:

file1.h #define USD 1 file2.h #define UKP 1 file3 #include #include //A #if !defined (USD) || !defined (UKP) // B #error "ERROR: NO_CURRENCY rate is specified." //C #endif main() { int rs; rs = 10 * currency_rate; //D printf ("%d ", rs); }

Explanation

  1. Statement B checks whether UKP or USD is defined.
  2. If both are not defined then the preprocessor displays an error.

Points to Remember

  1. The #error directive allows us to specify an error message.
  2. The error message is generated by the preprocessor.

#line

Introduction

The #line directive allows you to define arbitrary line numbers for the source lines. Normally, the compiler counts lines starting at line number 1; using the #line directive, you can specify an arbitrary line number at any point. The compiler then uses that line number for subsequent counts.

Program

#include main() { printf("A "); //A #line100 //H printf("B "); //B printf("C FILE %s LINE %d ", __FILE__, __LINE__ );//C #line200 //K printf("D "); //D printf("E "); //E }

Explanation

  1. The statement H indicates the #line directive.
  2. The #line number in statement B is taken as 100 and for statement C, it is taken as 101.
  3. The #line number in statement D is taken as 200 and for statement E, it is taken as 201.
  4. If you introduce any error in statement B then the compiler will display the error at #line number 100.
  5. C has provided two special identifiers: __FILE__ and __LINE__, which indicate the file name of the source file and the current line number, respectively.

Point to Remember

#line is used to indicate line numbers which can be used for debugging.

MACRO

Introduction

Macros allow replacement of the identifier by using a statement or expression. The replacement text is called the macro body. C uses macros extensively in its standard header files, such as in getchar(), getc().

Program

#define CUBE(x) x*x*x //A #include main () { int k = 5; int j = 0; j = CUBE(k); //B j = k*k*k printf ("value of j is %d ", j); //C }

Explanation

  1. You can define the macro CUBE as in statement A.
  2. The macro can be defined by using parameters, but that is not mandatory.
  3. The parameter name that is used in a macro definition is called the formal parameter. In this example, it is x.
  4. x*x*x is called the macro body.
  5. There should not be any spaces between the macro name and the left parenthesis.
  6. CUBE(k) in statement B indicates a macro call.
  7. An argument such as k, which is used for calling a macro, is called an actual parameter.
  8. While expanding the macro, the actual parameter is substituted in the formal parameter and the macro is expanded. So you will get the expansion as j = k*k*k.
  9. The value of j is calculated as 125.
  10. Since macro expansion is mainly a replacement, you can use any data type for the actual parameter. So, the above macro works well for the float data type.

Points to Remember

  1. A macro is used when you want to replace a symbol with an expression or a statement.
  2. You can define macros by using parameters.

MACRO AND FUNCTION

Introduction

While writing the macro, you have to write the macro body carefully because the macro just indicates replacement, not the function call.

Program

#include #define add(x1, y1) x1+y1 //E #define mult(x1,y2) x2*y2 //F main () { int a,b,c,d,e; a = 2; b = 3; c = 4; d = 5; e = mult(add(a, b), add(c, d)); //A // mult(a+b, c+d) //B // a+b * c+d //C printf ("The value of e is %d ", e); }

Explanation

  1. Statement E indicates a macro for adding two numbers.
  2. Statement F indicates a macro for multiplying two numbers.
  3. Statement A indicates a macro that is supposed to add two numbers and then multiply two numbers. In this case, it is supposed to perform the calculation (2+3) * (4+5).
  4. The actual expansion of macro adds is given in statement B.
  5. The final expansion of mult gives the expansion a+b * c+d, which is erroneous.
  6. The final value of e is 17, which is not correct.
  7. To get the correct value, use the following definition:

    #define add(x1, y1) (x1+y1) #define mult(x2, y2) (x2*y2)

Point to Remember

While using the macro, you have to write the expression correctly. You can use parentheses to give the correct meaning to the expression.

Категории