The C preprocessor directives are executed before the compilation of a program. It is not a part of the compiler and it is a separate step in the compilation process. It instructs the compiler to do the required pre-processing before the actual compilation of a program. So it is just a text substitution tool. There are several steps present in between writing a program and executing a program.
The programmer writes a source code and stores it in a file program. c. This file is then processed by preprocessors and an expanded source code file gets generated named as a program. The compiler compiles this expanded source code file and generates an object code file named the program. obj. This object code file and an object code of library functions are linked by the linker. This linking generates an executable file program.exe. The required results are obtained by executing the program.exe file.
The hash symbol (#) is the beginning of all preprocessor commands. Without preprocessors, our source code is not ready for compilation. The source code is processed by the preprocessors. This process is responsible for the expansion of source code. The compiler compiles this expanded file of source code.
Sr. no. | Processor Directives | Description |
1 | #define | Substitution of a processor macro. |
2 | #include | Insertion of the mentioned header file. |
3 | #undef | Undefining of a preprocessor macro. |
4 | #ifdef | If the mentioned macro is defined, then it returns true. |
5 | #ifndef | If the mentioned macro is not defined, then it returns true. |
6 | #if | Testing of a compile-time condition. |
7 | #else | Testing of a compile-time condition when the condition in #if is false. |
8 | #elif | This one preprocessor includes both #else and #if. |
9 | #endif | Ending of preprocessor condition. |
10 | #error | On stderr, it prints an error message. |
11 | #pragma | Specialized command is issued by it using a standardized method. |
Sr. no. | Macro | Description |
1 | __DATE__ | It returns the current date. The format of this date is ‘MMM DD YYYY’. |
2 | __TIME__ | It returns the current time. The format of this character string time literal is ‘HH:MM: SS’. |
3 | __FILE__ | It contains the current filename. This filename is in a string literal format. |
4 | __LINE__ | It contains the current line number. This filename is in a decimal constant format. |
5 | __STDC__ | If the compiler complies with the ANSI standard then it is defined as 1. |
The below program demonstrates the use of predefined macros:
#include <stdio.h> int main(void) { printf("The current file is: %s\n", __FILE__); printf("The current line is: %s\n", __LINE__); printf("The current date is: %s\n", __DATE__); printf("The current time is: %s\n", __TIME__); printf("The ANSI standard is: %s\n", __STDC__); return 0; }
The output is as below:
The current file is a demo.c The current line is: 6 The current date is: Dec 18 2020 The current time is: 17:51:52 The ANSI standard is: 1
Sr. no. | Operators | Description |
1 | \ | It is the macro continuation operator. A macro becomes too long to confine in a single line after using it. |
2 | # | It is the number-sign or stringize operator. A macro parameter converts into a string constant. |
3 | ## | It is the token pasting operator. It combines two arguments. Two separate tokens to be joined into a single token in a macro definition by it. |
4 | defined() | It is the defined operator. It is used in a constant expression. It determines if an identifier is defined using #define. |
The below program demonstrates the use of preprocessor operators such as #, \ and ##:
#include <stdio.h> # define message (first, second) printf(#first " and " #second" both test the code.\n" ) int main(void) { message (The Developer , tester); return 0; }
The output is as below:
The Developer and tester both test the code.
#include <stdio.h> # define tokenno(n) printf("token" #n " = %d", token##n) int main(void) { int token24=40; tokenno(24); return 0; }
The output is as below:
token24 = 40
It is used in constant expressions. It is used to determine if an identifier is defined using #define. If the specified identifier is defined, the value is true (non-zero) otherwise the value is false (zero). The defined operator is given as follows:
#include <stdio.h> #if !defined(STRING) #define STRING "I am a developer." #endif int main(void) { printf("The string is: %s\n", STRING); return 0; }
The output is as below:
The string is: I am a developer.
The parameterized macros can simulate functions and can also handle parameters. Consider the following function:
int cube(int number) { return number*number*number* ; }
Now, consider a macro as below:
#define cube(number) ((number)*(number)*(number))
The macros with arguments are always defined by using the #define directive. The parentheses contain an argument list. So, both macro and function above perform the same task. The spaces between the macro name and an open parenthesis give an error.
The below program demonstrates the implementation of the parameterized macro:
#include<stdio.h> #define COMPARE (firstnumber,secondnumber) ((firstnumber)>(secondnumber)?(firstnumber):(secondnumber)) int main(void) { printf("The bigger number is: %d",COMPARE(10,20)); return 0; }
The output is as below:
The bigger number is: 20
It is a named piece of code in the program. When the compiler gets this name, the name is replaced with the actual code which belongs to it. The best example of macros is the #define preprocessor directive. This directive defines a macro.
Consider the program below:
#include <stdio.h> //definition of MACRO directive #define COUNT 4 int main(void) { inti; for (i=0;i<=COUNT;i++) { printf("The number is: %d \n",i); } return 0; }
The output is as below:
The number is: 0 The number is: 1 The number is: 2 The number is: 3 The number is: 4
In the above program, the word COUNT is replaced by number 4. The word COUNT is working as a macro template. The number 4 is working as a macro expansion. There is no need to put a semi-colon (;) at the end of the macro definition.
The arguments can be passed to macros. Consider the program below:
#include <stdio.h> //definition of MACRO directive #define VOLUME (length, breadth, height) (length*breadth*height) int main(void) { int length= 4, breadth=5, height=6, volume; volume= VOLUME(length, breadth, height); printf("The volume of a cube is: %d sq.unit",volume); return 0; }
The output is as below:
The volume of a cube is: 120 sq. unit
In the above program, VOLUME (length, breadth, height) is replaced by the statement (length*breadth*height) when the compiler encounters it. After this, values are passed to the macro template and it becomes VOLUME (4, 5, 6). So, the statement (length*breadth*height) becomes (4*5*6) and gives the required result.
These preprocessor directives include a file in the source code with help of the compiler. This directive has two types.
The header or standard files includes printf(), scanf(), and other similar functions. Different header files have different functions. The standard I/O functions are present in theiostream.h header file. Similarly, the standard string-related functions are present in the string.h header file. Without these preprocessor directives, the functions mentioned above will not work. The syntax is as below:
#include <file_name> The file_nameis the name of a file we needed with the related functions. The program below demonstrates the implementation of the header or standard files: #include <stdio.h> int main(void) { printf("I am a developer."); return 0; }
The output is as below:
I am a developer.
The < and > brackets instruct the compiler to search the mentioned file in the standard directory.
The user-defined files are used to break large code and include the required files only at the required place. The syntax is as below:
#include "file_name"
The program below demonstrates the implementation of the user-defined files:
#include "stdio.h" int main(void) { printf("I am a developer."); return 0; }
The output is as below:
I am a developer.
These directives either compile or skip a specific part of the source code. The working of these directives is dependent upon the conditions mentioned in them. These directives include #if, #elif, #else, #endif, #ifdef. The syntax is as below:
#if Macro_Conditions conditional_statements #elifMacro_Conditions conditional_statements #else Macro_Conditions conditional_statements #endif
The program below demonstrates the implementation of conditional compiling preprocessor directives:
#include <stdio.h> int main(void) { intfirstnumber,secondnumber; printf("Enter two numbers:\n"); scanf("%d%d",&firstnumber,&secondnumber); #if 3>9 printf("Sum %d",firstnumber+secondnumber); #else if(firstnumber == secondnumber) printf("Both number are same."); else if(firstnumber>secondnumber) printf("The larger numbers is %d",firstnumber); else printf("The larger number is %d",secondnumber); #endif return 0; }
The output is as below:
Enter two numbers: 6 8 The larger number is 8.
Some preprocessor directives are not used regularly. The compiler can skip them if they are not defined. Such directives are as below:
#undef directive:
This directive undefines a macro if it exists. The syntax for this is:
#undefMacro_name e.g. #undef LIMIT
#pragma directives:
This is a special purpose directive. The main function of this directive is to turn on and off some features. These directives can specify the functions too.
These directives redirect the flow of compilation of program towards the functions which are required just before program control passes to main and just before control returns to main. The program below demonstrates the implementation of conditional #pragma directives:
#include<stdio.h> voidfirstfunction(); voidsecondfunction(); #pragma startup firstfunction #pragma startup secondfunction voidfirstfunction() { printf("Inside the first function.\n"); } voidsecondfunction() { printf("Inside the second function.\n"); } int main(void) { voidfirstfunction(); voidsecondfunction(); printf("Inside the main function.\n"); return (0); }
The output is as below:
Inside the first function. Inside the main function. Inside the second function.
#pragma warn directives:
These directives are used to hide the warning messages. Generally, these warning messages are created during the compilation of a program. Types of these directives are as below:
Thus, in this tutorial, we have seen various preprocessor directives provided by C language along with their examples. The preprocessor directives help us to write more efficient programs and more readable programs to some extent.