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 ## b

If 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.