Modern C (C11/C17/C23)

stringizing (#) and token-pasting (##)

/ STRING-eye-zing /

The preprocessor has two special operators that build text. Stringizing, written with a single #, turns a macro argument into a string literal: whatever you pass becomes characters between quotes. Token-pasting, written with ##, glues two tokens together to form one new token. Both happen during preprocessing, before the compiler proper ever sees the code.

Stringizing: in #define STR(x) #x, calling STR(hello) yields the literal "hello", and STR(1+2) yields "1+2" — the argument's text is captured verbatim and wrapped in quotes. Token-pasting: in #define CAT(a,b) a##b, calling CAT(foo, bar) produces the single identifier foobar; this is how you can build a variable or function name out of pieces. A useful subtlety is the two-level macro trick: to stringize the VALUE of another macro rather than its name, you go through a helper, as in #define STR(x) #x and #define XSTR(x) STR(x), so XSTR(VERSION) expands VERSION first and then stringizes the result.

They matter for code generation, debugging helpers (printing an expression and its value), and building identifiers from a base name. The caveats: # and ## operate on the raw, UN-expanded argument tokens, which is exactly why the extra indirection layer is needed to expand a macro before pasting or stringizing; and pasting tokens that do not form a single valid token is undefined behavior.

#define STR(x) #x #define XSTR(x) STR(x) // expand x first, then stringize #define CAT(a,b) a##b #define VERSION 3 XSTR(VERSION) // -> "3" (STR(VERSION) would give "VERSION") CAT(my_, fn) // -> identifier my_fn

# quotes an argument's text; ## glues tokens; the two-layer XSTR trick forces the inner macro to expand first.

# and ## act on the raw, unexpanded argument, so to stringize or paste a macro's VALUE you need an extra indirection layer; pasting into an invalid token is undefined behavior.

Also called
stringificationtoken concatenation字串化與符號連接運算子