With the requirement to include file inclusion procedures present in PL/I and BPCL, the preprocessors were introduced in C at the time of 1973 with the request of Alan Snyder. The initial version of the preprocessor provided only file inclusion procedures and string replacement through #include and #define. Whereas the later versions of (John Reiser and Mike Lesk) offered macros together with arguments and conditional compilations. That’s how the development of the preprocessor took place and now this article helps us in knowing the preprocessor definition, syntax, types, commands, and its advantages.
What is Preprocessor?
In the C programming, during code compilation, a person expects the compiler performs code compilation as per how the code is written, but this is not the actual scenario. Before code compilation, the file where the code is written passes through a stage called translation which is termed a translation unit. So, the C preprocessor definition is termed as a macro processor which the C compiler automatically uses it for the transformation of the program prior to the compilation phase. This preprocessor is termed as a macro because one can define macros (short abbreviations for lengthy constructs).
The preprocessor scans every code file and looks for preprocessor directives (directives) and they have their own syntaxes. These directives are the instructions that start with a preprocessor symbol # and ends with a newline. The directives allow the preprocessor to execute specific text manipulation operations. The output from this stage passes through many translation stages and then moves to the compilation phase.
The below picture shows the chain of tasks in a preprocessor.
Types
These preprocessor commands are identified with a preprocessor symbol ‘#’ followed by the identifier and name of the directive. A few of the types of preprocessor in C are:
- Header files inclusion
- Macros expansion
- Conditional compilation
- Line controlling
A few of the types in preprocessor directives are explained as follows:
Macros
Every macro is provided with some name and these macros are some portion of code in the program. At the time, when the compiler observes the macro name, it substitutes the name with actual code. #define is the preprocessor directive used in defining a macro.
The preprocessor syntax for define is
#define taken value
#define AREA (a, b) (a * b) – function like macros
#define PI 3.14
Example –
#include <stdio.h>
#define LIMIT 10
int main()
{
for (int p = 0; p < LIMIT; p++) {
Printf(“%d \n”, p);
}
return 0;
}
As per the above example, ‘LIMIT’ is termed as a macro template, and ‘10’ is termed as a macro expansion.
File Inclusion
The file inclusion directive allows the compiler to include a source code file in the program and a person can include two kinds of files in the program which are:
Standard/Header files – The header files consist of pre-defined functions such as scanf(), print(), and others. In order to use the operations in those files, one must include the corresponding header files. There exist various types of header files for various operations where string file contains string operations and iostream contains input and output functions.
The syntax is
#include <file name>
User-Defined files – When there is a lengthy program, the user can divide it into smaller files and include corresponding functions. The syntax for user defines files is #define “filename”.
Conditional Compilation
These directives help in deciding whether some portion of the code can be compiled or not depending on a few rules/conditions. This decision can be done using two preprocessor directives which are endif and ifdef. The syntax is:
#ifdef MACRO_NAME
Statement a;
Statement b;
.
.
Statement N;
#endif
As per the above syntax, when the macro name is defined along with the macro, then the below statements are executed properly, if not defined with macro name then the statements between ifdef and endif are not executed.
Other Directives
Apart from the above directives, the other directives which are not generally used are:
#undef – This directive helps in undefining existing macros. The syntax is #undef LIMIT
After undefining a macro in the code, the latter part of the code will not be evaluated.
#pragma – With this directive, few functions can be either turned ON or turned OFF and these vary for different compilers. This directive also provides added data to the compiler. The syntax is
#pragma token
#pragma startup & #pragma exit – These preprocessor directives are helpful in specifying the functions which are not required to run the program in before program startup and just before the program exits.
Example:
#include <stdio.h>
void function1();
void function2();
#pragma startup function1
#pragma exit function2
void function1()
{
printf(“Inner function1()\n”);
}
void function2()
{
printf(“Inner func2()\n”);
}
int main()
{
void function1();
void function2();
printf(“Inner main()\n”);
return 0;
}
#pragma warn – At the time of compilation, when there are any warning messages, this directive helps in hiding those messages. The messages can be hidden as follows:
- #pragma warn – rvl – It hides the warning message those arise when a function is anticipated to return a value but does not return.
- #pragma warn – par – It hides the warning message those arise when a function does not use the parameters which are passed to it.
- #pragma warn – rch – It hides the warning message those arise when the program code is not reachable.
Difference b/w Preprocessor and Postprocessor
- A pre-processor is considered as a component that gets invoked before the data passes to the external informational source. With this, a developer can include any kind of logic in the data before the request gets forwarded to an external source. Whereas postprocessor is also a component but the component gets invoked after data receives from an external source but before the data is passed on to the external device. With this, a developer can include any kind of logic in the data before the response is transmitted to the external device.
- The logic behind formatting and removing data elements and logging of data elements appear the same.
- The operations performed by preprocessors and postprocessors on the data which is transmitted to the service are filtering, adding, deleting, and modifying the format of data.
Difference between Preprocessor and Compiler
- A preprocessor looks into the source code file and executes multiple preprocessing activities before the code is compiled by the compiler.
- The compiler is responsible for setting up the source code file through various translation stages before moving to preprocess stage.
- A preprocessor is considered to be a part of a compiler where it executes preliminary tasks such as the inclusion of files, expansion of macros, and conditional compiling for the code before compilation starts. Whereas the transformations are lexical (the preprocessor output is still in text format).
Advantages and Disadvantages
The preprocessor’s advantages and disadvantages are discussed below:
Advantages
- Helps in dividing the program into segments of tokens.
- It links together adjacent strings of constant character.
- It checks for comments in the program and substitutes those in a single space.
- Works in joining any number of lines through a backslash character and forms a single line.
- Substitutes Non-ASCII characters with their corresponding characters.
- Executes any task as per the special commands of preprocessor directives that start with the ‘#’ character.
Disadvantages
- Increased compilation time.
- The macros in preprocessors do not respect either the scope or usage in any approach.
- It is more recommended to not include preprocessors in the code unless one has a proper reason to include them.
- As the code is replaced with macros, the program length increases when the macro is called every t
Q: What is a preprocessor?
A: The preprocessor is a program that processes your code before it is compiled. It is called a preprocessor because it happens before the compilation process.
Q: What does the preprocessor do?
A: The preprocessor will replace all macros with their definitions, and expand all #include directives by inserting the contents of the included files.
Q: How do I use the preprocessor?
A: You can use the preprocessor by placing directives at the top of code files (or in other places) that tell the preprocessor to do something. In most cases, you will be using #define to create macro definitions and #include to include other files into your code file.
On the whole, the preprocessor output appears the same as the input other than all the directives are substituted either with whitespaces or empty lines. Different kinds of formats and files possess various types of syntaxes claiming that starting a new file or returning of file has to be done before compilation.
This article has explained preprocessor syntax, definition, and directives with examples and advantages. Know how the program in C++ language can be written with preprocessor directives?