Mastering Preprocessors in C

Preprocessors are programs that process the source code before compilation. They are not part of the compiler itself but a crucial step in the compilation process.
All preprocessor directives begin with the # symbol. The compiler does not understand # statements; they are handled by the preprocessor program first.
Types of Preprocessors
- Macros
- File Inclusion
- Conditional Compilation
- Other Directives
1. Macros
A Macro is a piece of code given a name. Whenever the compiler encounters this name, it replaces it with the actual piece of code. This is defined by the #define directive.
Types of Macros
- Object-like Macros: Replaces a name with a value snippet.
- Function-like Macros: Replaces a name with arguments like a function call.
Predefined Macros
__DATE__Current date in "MMM DD YYYY"
__TIME__Current time in "HH:MM:SS"
__FILE__Current file name
__LINE__Current line number
Advantages
- Code Reuse: Declare once, use multiple times.
- Code Abbreviation: Makes code more expressive and readable.
- Performance Optimization: Avoids function call overhead (though modern compilers often inline functions anyway).
2. File Inclusion
Changes the current file by including another file's content. The #include directive is used for this.
1. Standard Header File
#include <filename>Tells the compiler to look in the system directory (e.g., /usr/include).
2. User Defined Header File
#include "filename"Tells the compiler to look in the current directory first.
Example
#include <stdio.h>
int main() {
printf("Hello C");
return 0;
}3. Conditional Compilation
Directives like #if, #ifdef, #ifndef, #else, and #endif allow you to compile specific parts of code based on conditions.
Note: #endif is mandatory to close any conditional block.
#include <stdio.h>
#define A 50
#define B 7
int main() {
int result;
#if (A > B)
result = A + B;
printf("sum = %d", result);
#else
result = A - B;
printf("diff = %d", result);
#endif
return 0;
}4. Other Directives
#undef Directive
Used to undefine an existing macro.
#include <stdio.h>
#define VALUE 10
int main() {
printf("Min value is: %d\n", VALUE);
#undef VALUE
#define VALUE 20
printf("After undef and redefine: %d\n", VALUE);
return 0;
}#pragma Directive
Used to provide additional information to the compiler, often specific to the machine or OS. Usage varies by compiler.
Common Pragma tokens (supported by Turbo C++ and others):
- #pragma argsused
- #pragma exit
- #pragma hdrfile
- #pragma hdrstop
- #pragma inline
- #pragma option
- #pragma saveregs
- #pragma startup
- #pragma warn
C23: New Preprocessor Directives
The C23 standard introduced two new conditional compilation directives that simplify common patterns:
#elifdefA shorthand for #elif defined(NAME). Eliminates the need for the verbose two-word pattern when chaining macro checks.
// Old way (C17)
#elif defined(PLATFORM_LINUX)
// New way (C23)
#elifdef PLATFORM_LINUX#elifndefA shorthand for #elif !defined(NAME). Checks that a macro is not defined, complementing #elifdef.
These directives are now supported in GCC 13+, Clang 16+, and MSVC 2022 17.5+.
Frequently Asked Questions
Q: Which directive terminates conditional compilation?
A: #endif
Q: Which directive is used to declare macros?
A: #define
Q: List 4 common preprocessing directives.
A: #include, #define, #pragma, #if
Q: What is the main purpose of #include?
A: To tell the compiler to include the contents of a file in the source program.