C Language | Preprocessing | Function-like Macros - #define

A function-like macro accepts parameters and expands arbitrary text through the #define directive. It can resemble a function without introducing function-call overhead because expansion occurs before compilation.

Macro Expansion with Parameters

Functions improve reuse, but even a small function call involves passing arguments and returning control to the caller. For simple calculations, a macro can expand an expression directly at compile time.

#define directive for a function-like macro

#define identifier(argument1, argument2 ...) token-sequence

For example:

#define ADD(a , b) a + b

ADD(10, 20) is replaced with 10 + 20 before compilation.

Code 1

#include <stdio.h>
#define MUL(multiplicand , multiplier) multiplicand * multiplier

int main() {
 printf("5 * 5 = %d\n" , MUL(5 , 5));
 return 0;
}

Macro expansion is textual, which can cause unexpected operator precedence.

Code 2

#include <stdio.h>

#define MUL(multiplicand , multiplier) multiplicand * multiplier
int mul(int multiplicand , int multiplier) {
 return multiplicand * multiplier;
}

int main() {
 printf("macro: MUL(3 + 2 , 5) = %d\n" , MUL(3 + 2 , 5));
 printf("function: mul(3 + 2 , 5) = %d\n" , mul(3 + 2 , 5));
 return 0;
}

The regular function returns 25, but the macro expands to 3 + 2 * 5 and returns 13. Protect each argument and the entire expression with parentheses:

#define MUL(multiplicand , multiplier) ((multiplicand) * (multiplier))

Macros are useful for concise bit operations.

Code 3

#include <stdio.h>

typedef unsigned char BYTE;
#define RGB(r , g , b) ((BYTE)(r) << 16) | ((BYTE)(g) << 8) | (BYTE)(b)
#define RED(color) (BYTE)((color) >> 16)
#define GREEN(color) (BYTE)((color) >> 8)
#define BLUE(color) (BYTE)(color)

int main() {
 int color = RGB(0xFF , 0xEE , 0xAA);
 printf("R = %X : G = %X : B = %X\n" ,
   RED(color) , GREEN(color) , BLUE(color));
 return 0;
}

This example stores red, green, and blue components in one integer and extracts each byte with a macro. Function-like macros are commonly used for small transformations and for wrapping repetitive calls, but their textual expansion must always be considered.