The C preprocessor processes source code before the actual compilation
takes place. Preprocessor directives are instructions that begin with
the # symbol and are used for tasks such as including header
files, defining macros, and conditionally compiling code.
The preprocessor is a program that processes C source code before it is passed to the compiler.
It performs tasks such as:
A preprocessor directive is an instruction for the preprocessor.
It begins with the # symbol.
#include <stdio.h>
The directive tells the preprocessor to include the required header information before compilation.
Some commonly used directives are:
#include#define#undef#if#ifdef#ifndef#else#elif#endif#pragma
The #include directive is used to include the contents or
interface declarations of a header file.
#include <stdio.h>
This allows a program to use declarations provided by the standard I/O header.
Standard library headers are commonly written using angle brackets.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
These headers provide declarations for standard library facilities.
A project can include its own header file using double quotes.
#include "myheader.h"
This is commonly used for header files created as part of a project.
The #define directive creates a macro.
#define PI 3.14159
Before compilation, occurrences of PI can be replaced by
the macro replacement text according to the preprocessor rules.
A macro without parameters is called an object-like macro.
#define MAX_STUDENTS 100
#define COMPANY "Soopro Pathshala"
Macros can represent numeric values, strings, or other preprocessing tokens.
#include <stdio.h>
#define PI 3.14159
int main()
{
float radius = 5.0f;
float area = PI * radius * radius;
printf("Area = %.2f", area);
return 0;
}
The preprocessor handles the PI macro before compilation.
A macro can also accept parameters.
#define SQUARE(x) ((x) * (x))
Example:
int result = SQUARE(5);
Parentheses are important when writing expression-like macros.
#define MAX(a, b) ((a) > (b) ? (a) : (b))
Example:
int largest = MAX(10, 20);
The macro replacement text uses parentheses to reduce unexpected precedence problems.
| Macro | Function |
|---|---|
| Handled by the preprocessor | Handled by the compiler as a function |
| Text/token substitution | Has normal function call semantics |
| No normal parameter type checking | Parameters have declared types |
| Can cause repeated evaluation of an argument | Arguments are evaluated according to function-call rules |
For many ordinary calculations, a function is often easier to reason about.
The #undef directive removes a macro definition.
#define VALUE 100
#undef VALUE
After #undef, the macro VALUE is no longer defined
for subsequent preprocessing.
Conditional compilation allows selected sections of source code to be included or excluded based on preprocessing conditions.
#if CONDITION
/* code */
#endif
The preprocessor evaluates the condition before compilation.
The #if directive includes code when its preprocessing
expression evaluates to a nonzero value.
#define DEBUG 1
#if DEBUG
printf("Debug mode");
#endif
The #ifdef directive checks whether a macro is defined.
#define DEBUG
#ifdef DEBUG
printf("Debugging enabled");
#endif
The code inside the conditional section is included because
DEBUG is defined.
The #ifndef directive checks whether a macro is not defined.
#ifndef VERSION
#define VERSION 1
#endif
This is frequently used in header guards.
The #else directive provides an alternative section when a
preprocessing condition is false.
#ifdef DEBUG
printf("Debug mode");
#else
printf("Normal mode");
#endif
The #elif directive allows another preprocessing condition
to be tested.
#if VERSION == 1
printf("Version 1");
#elif VERSION == 2
printf("Version 2");
#else
printf("Other version");
#endif
The #endif directive ends a conditional preprocessing block.
#ifdef DEBUG
printf("Debug information");
#endif
Every conditional block started by directives such as
#if, #ifdef, or #ifndef must be
properly terminated.
Header guards prevent the same header contents from being processed multiple times in a single translation unit.
#ifndef MYHEADER_H
#define MYHEADER_H
void display(void);
#endif
This pattern is commonly used in user-defined header files.
C implementations provide several predefined macros. Common examples include:
__FILE__ – source file name__LINE__ – current source line number__DATE__ – compilation date__TIME__ – compilation timeprintf("File: %s\n", __FILE__);
printf("Line: %d\n", __LINE__);
These predefined macros are useful for diagnostics and debugging.
#include <stdio.h>
int main()
{
printf("File: %s\n", __FILE__);
printf("Line: %d\n", __LINE__);
return 0;
}
Inside a function-like macro, the # operator can convert a
macro argument into a string literal.
#define SHOW(x) printf(#x " = %d\n", x)
SHOW(10 + 20);
The stringizing operation is a preprocessor feature and is different from
the #include directive.
The ## operator combines two preprocessing tokens into one
token.
#define JOIN(a, b) a ## b
int JOIN(value, 1) = 100;
This can create an identifier such as value1.
Function-like macros can produce unexpected results if parameters are not properly parenthesized.
A risky macro is:
#define SQUARE(x) x * x
For example, SQUARE(2 + 3) can expand in an unexpected way.
A safer form is:
#define SQUARE(x) ((x) * (x))
#include <stdio.h>
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int main()
{
int a = 5;
int b = 10;
printf("Square of %d = %d\n", a, SQUARE(a));
printf("Largest = %d\n", MAX(a, b));
return 0;
}
#include <stdio.h>
#define DEBUG
int main()
{
#ifdef DEBUG
printf("Debug information is enabled.\n");
#else
printf("Debug information is disabled.\n");
#endif
printf("Program is running.");
return 0;
}
The section selected by the preprocessor depends on whether
DEBUG is defined.
Create a C program that:
PI.#ifdef for a debug message.#if with a version macro.__FILE__ and __LINE__.#include.This exercise will help you understand macros, conditional compilation, header guards, and predefined macros.
# symbol.#include includes header files.#define creates macros.#undef removes a macro definition.#if, #ifdef, and #ifndef are used for conditional compilation.#else and #elif provide alternative conditions.#endif ends a conditional block.__FILE__ and __LINE__ are useful predefined macros.# operator can stringify a macro argument.## operator can paste preprocessing tokens together.Question: Which preprocessor directive is used to include a header file?