In C, macros are a feature provided by the preprocessor to perform text substitution before the program is compiled. They are defined using the #define directive and provide a way to write reusable and concise code.
Definition
A macro is a fragment of code or a constant name that is replaced by its value or a block of code during preprocessing.
Types of Macros
Macros in C can be broadly classified into the following types:
—
- Object-like Macros
– These are simple macros that replace a name with a constant or a value.
– Commonly used to define constants.
Syntax:
c
#define MACRO_NAME value
Example:
c
#define PI 3.14159
#define MAX 100
int main() {
printf(“Value of PI: %f\n”, PI);
printf(“Maximum value: %d\n”, MAX);
return 0;
}
—
- Function-like Macros
– These macros behave like functions but are faster as they are expanded inline during preprocessing.
– They can take arguments.
Syntax:
c
#define MACRO_NAME(parameters) expression
Example:
c
#define SQUARE(x)1
#define MAX(a, b)2
int main() {
printf(“Square of 5: %d\n”, SQUARE(5));
printf(“Maximum of 10 and 20: %d\n”, MAX(10, 20));
return 0;
}
Note: Parentheses are essential to avoid operator precedence issues.
—
- Conditional Macros
– Used in conjunction with preprocessor directives like #if, #ifdef, #ifndef, #else, #elif, and #endif.
– Allow conditional compilation based on macro definitions.
Syntax:
c
#ifdef MACRO_NAME
// Code when MACRO_NAME is defined
#else
// Code when MACRO_NAME is not defined
#endif
Example:
c
#define DEBUG
int main() {
#ifdef DEBUG
printf(“Debug mode is ON.\n”);
#else
printf(“Debug mode is OFF.\n”);
#endif
return 0;
}
—
- File Inclusion Macros
– Used to include the contents of other files in the program.
– The directives #include can be used with angle brackets (< >) for system files or double quotes (” “) for user-defined files.
Syntax:
c
#include <header_file>
#include “user_defined_file”
Example:
c
#include <stdio.h> // Standard library
#include “myheader.h” // User-defined header
—
- Stringizing and Token Pasting Macros
These are advanced macros used for manipulating tokens.
Stringizing (#)
– Converts a macro argument into a string literal.
Example:
c
#define STRINGIFY(x) #x
int main() {
printf(“%s\n”, STRINGIFY(Hello, World!));
return 0;
}
Token Pasting (##)
– Concatenates two tokens into a single token.
Example:
c
#define CONCAT(a, b) a##b
int main() {
int xy = 10;
printf(“%d\n”, CONCAT(x, y)); // Expands to xy
return 0;
}
—
- Variadic Macros (Introduced in C99)
– These macros can accept a variable number of arguments.
Syntax:
c
#define MACRO_NAME(…) expression
Example:
c
#include <stdio.h>
#define PRINT(fmt, …) printf(fmt, __VA_ARGS__)
int main() {
PRINT(“Sum of %d and %d is %d\n”, 10, 20, 10 + 20);
return 0;
}
—
Advantages of Macros
– Reduces code duplication.
– Improves code readability and maintainability.
– Offers better performance than function calls.
Disadvantages of Macros
– Lack of type checking.
– Can lead to debugging challenges.
– May result in code bloat due to inline expansion.
When to Use Macros?
– Use macros for constants or inline code that requires preprocessing.
– For complex operations, prefer const, inline functions, or enum for better type safety and debugging