c++cmacros

Macros in C language cannot be expanding correctly


I wrote the following macro in C language:

#define STR(x) #x

I expect the following call to produce the result "11":

STR(5+6)

But the actual result it produces is "5+6"

How can I write macros to achieve the results I want? Is it possible to implement it in C or C++ language?


Solution

  • Macros are text replacements[1] done by the C Preprocessor; a tool that runs over your code before the compiler itself ever sees it, and consequently, before any compile-time constant expressions (such as 5+6) are evaluated. The preprocessor can do some arithmetic and comparisons to implement conditional compilation via the #if / #elif / #else directives, but no evaluation is performed in macro expansions outside of such conditional expressions (Thanks to @interjay for pointing this out).

    Most importantly, the preprocessor has no notion of the language you're writing in. It doesn't know any of the syntax or semantics of either C or C++.

    This is the main reason why in the C++ world, macros are generally considered "evil" (read: should be avoided unless absolutely necessary). Note that the result you want here, parsing a compile-time-evaluated number into a compile-time-evaluated string, cannot be generally achieved even in the most recent C++ standard revision. constexpr strings do exist, but they do not survive long: See Is it possible to use std::string in a constant expression?

    Bottom line: Can't be done, you have to do it at runtime.


    [1] As @Lundin has correctly pointed out, "text replacement" is an oversimplification here. The preprocessing rules implement a set of functions that operate on well-defined tokens, not just on any arbitrary string. For example, processing STR(x) #x with the expression STR(1+1) produces the string constant "1+1" (not simply the replacement #1+1 as you'd expect from a regular macro expansion).
    The core issue remains however that the preprocessing is a single-pass run over your code whose language has different rules from C or C++ because it was designed to save you typing work on your files and automatically prepare them before they're given to the compiler.
    Nontheless, @Lundin is right in that calling the preprocessor a pure text replacement tool doesn't do it justice.