What Is the Token-Pasting Operator in C?
The token-pasting operator, represented by double hashes
(##), is a preprocessor feature in the C programming
language used within macro definitions to merge two lexical tokens into
a single valid token. This article explains how the token-pasting
operator functions, why developers use it to generate dynamic
identifiers and eliminate repetitive boilerplate code, and the essential
rules to follow when implementing it.
How the Token-Pasting Operator Works
During the preprocessing stage of compilation, the preprocessor
evaluates macros before any actual C code compilation takes place. When
the ## operator appears in the replacement list of a macro
definition, it takes the tokens immediately preceding and following it,
eliminates any surrounding whitespace, and concatenates them into a
single token.
For example, consider the following macro definition:
#define CONCAT(a, b) a ## bIf invoked as CONCAT(var, 1), the preprocessor replaces
it with var1.
Key Use Cases
1. Dynamic Identifier Generation
The most common use of the ## operator is to dynamically
generate unique variable names, function names, or typedefs. This is
particularly valuable in creating pseudo-generic functions or data
structures in C.
#include <stdio.h>
#define DEFINE_PRINT_FUNCTION(type, format) \
void print_ ## type(type value) { \
printf(format "\n", value); \
}
DEFINE_PRINT_FUNCTION(int, "%d")
DEFINE_PRINT_FUNCTION(double, "%f")
int main(void) {
print_int(42);
print_double(3.14);
return 0;
}In this example, print_ ## type expands to create the
identifiers print_int and print_double.
2. Boilerplate Code Reduction
When writing modular code, APIs, or hardware drivers, developers often have to declare dozens of nearly identical functions or variables differing only by a numeric index or data type. The token-pasting operator lets you generate these blocks through single-line macro invocations, reducing manual typing and preventing copy-paste bugs.
Important Rules and Constraints
- Valid Token Creation: The concatenated result must
form a valid C token (such as a valid identifier, number, or operator).
Concatenating tokens that produce an illegal token (such as merging
+and*) results in undefined behavior or a compile-time error. - Placement Restrictions: The
##operator cannot appear at the absolute beginning or the absolute end of a macro replacement list. It must always sit between two tokens. - Argument Expansion and Indirection: If an argument passed to a token-pasting macro is itself another macro, it will not be expanded before concatenation. To force the preprocessor to expand the macro argument first, you must introduce a layer of indirection:
#define GLUE(a, b) a ## b
#define CONCAT(a, b) GLUE(a, b)
#define PREFIX count
#define SUFFIX 5
// Directly using GLUE(PREFIX, SUFFIX) yields "PREFIXSUFFIX"
// Using CONCAT(PREFIX, SUFFIX) yields "count5"The token-pasting operator gives developers fine-grained control over metaprogramming in C, enabling code reuse and dynamic symbol naming while maintaining compile-time efficiency.