C Preprocessor
C Preprocessor is not part of the compiler, but it is a separate step in the compilation process. In short, the C Preprocessor is just a text substitution tool, and it instructs the compiler to perform necessary preprocessing before actual compilation. We will abbreviate the C Preprocessor (C Preprocessor) as CPP.
All preprocessor commands start with a hash symbol (#). It must be the first non-blank character, and for readability, preprocessor directives should start in the first column. Below is a list of all important preprocessor directives:
Directive | Description |
---|---|
#define | Define a macro |
#include | Include a source code file |
#undef | Undefine a macro |
#ifdef | Return true if the macro is defined |
#ifndef | Return true if the macro is not defined |
#if | Compile the following code if the given condition is true |
#else | Alternative for #if |
#elif | Compile the following code if the previous #if condition is not true and the current condition is true |
#endif | End of a #if……#else conditional compilation block |
#error | Output an error message when encountering a standard error |
#pragma | Issue special commands to the compiler using a standardized method |
Preprocessor Example
Analyze the following example to understand different directives.
#define MAX_ARRAY_LENGTH 20
This directive tells CPP to replace all occurrences of MAX_ARRAY_LENGTH with 20. Using #define to define constants enhances readability.
#include <stdio.h>
#include "myheader.h"
These directives tell CPP to get stdio.h from the system libraries and add the text to the current source file. The next line tells CPP to get myheader.h from the local directory and add its content to the current source file.
#undef FILE_SIZE
#define FILE_SIZE 42
This directive tells CPP to undefine the already defined FILE_SIZE and define it as 42.
#ifndef MESSAGE
#define MESSAGE "You wish!"
#endif
This directive tells CPP to define MESSAGE only if MESSAGE is not already defined.
#ifdef DEBUG
/* Your debugging statements here */
#endif
This directive tells CPP to process the statements if DEBUG is defined. This is useful when you pass the -DDEBUG switch to the gcc compiler during compilation. It defines DEBUG, allowing you to turn debugging on and off at compile time.
Predefined Macros
ANSI C defines many macros. You can use these macros in your programming, but you cannot modify them directly.
Macro | Description |
---|---|
__DATE__ | The current date, a character constant in "MMM DD YYYY" format. |
__TIME__ | The current time, a character constant in "HH:MM:SS" format. |
__FILE__ | This contains the current filename, a string constant. |
__LINE__ | This contains the current line number, a decimal constant. |
__STDC__ | Defined as 1 when the compiler compiles with the ANSI standard. |
Let's try the following example:
#include <stdio.h>
main()
{
printf("File :%s\n", __FILE__ );
printf("Date :%s\n", __DATE__ );
printf("Time :%s\n", __TIME__ );
printf("Line :%d\n", __LINE__ );
printf("ANSI :%d\n", __STDC__ );
}
When the above code (in file test.c) is compiled and executed, it produces the following result:
File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1
Preprocessor Operators
The C Preprocessor offers the following operators to help create macros:
Macro Continuation Operator ()
A macro is typically written on a single line. If a macro is too long for a single line, the macro continuation operator () is used. For example:
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
Stringize Operator (#)
In a macro definition, the stringize operator (#) is used to convert a macro parameter into a string constant. This operator can be used within the macro definition only. For example:
#include <stdio.h>
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
int main(void)
{
message_for(Carole, Debra);
return 0;
}
When the above code is compiled and executed, it produces the following result:
Carole and Debra: We love you!
Token Pasting Operator (##)
The token pasting operator (##) in a macro definition combines two parameters. It allows two separate tokens in the macro definition to be combined into a single token. For example:
#include <stdio.h>
#define tokenpaster(n) printf ("token" #n " = %d", token##n)
int main(void)
{
int token34 = 40;
tokenpaster(34);
return 0;
}
When the above code is compiled and executed, it produces the following result:
token34 = 40
This happens because the example will produce the following actual output from the compiler:
printf ("token34 = %d", token34);
This example demonstrates how token##n concatenates to token34, and we used the stringize operator (#) and token pasting operator (##).
defined() Operator
The preprocessor defined operator is used in a constant expression to determine if an identifier is defined using #define. If the specified identifier is defined, the value is true (non-zero). If the specified identifier is not defined, the value is false (zero). The following example demonstrates the use of the defined() operator:
#include <stdio.h>
#if !defined (MESSAGE)
#define MESSAGE "You wish!"
#endif
int main(void)
{
printf("Here is the message: %s\n", MESSAGE);
return 0;
}
When the above code is compiled and executed, it produces the following result:
Here is the message: You wish!
Parameterized Macros
One of the powerful functions of the CPP is the ability to simulate functions using parameterized macros. For example, the following code computes the square of a number:
int square(int x) {
return x * x;
}
We can rewrite the above code using a macro as follows:
#define square(x) ((x) * (x))
Before using a macro with parameters, you must define it using the #define directive. The parameter list is enclosed in parentheses and must immediately follow the macro name. No spaces are allowed between the macro name and the opening parenthesis. For example:
#include <stdio.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))
int main(void)
{
printf("Max between 20 and 10 is %d\n", MAX(10, 20));
return 0;
}
When the above code is compiled and executed, it produces the following result:
Max between 20 and 10 is 20