c++ – Priority of preprocessor operations

Question:

Let's say we have this macro:

#include <iostream>

#define DEF(a,b) #a##b

int main()
{
    std::cout << DEF(3,4);
}

Is there any order in which expressions are evaluated in a macro, or does it all depend on the compiler?

Here DEF(3,4) is #3##4 . For example, if ## has a higher precedence, then it extends to #34 , and then to "34" . Otherwise, first "3"##4 , and then "3"4 (VS2008 does this).

Answer:

Three major compilers (gcc, clang, msvs) of recent versions report an error when trying to compile your code. At the same time, according to the standards of the C and C++ languages, the order of evaluation of the operators # and ## is not defined.

C:6.10.3.2 The # operator
C++: 15.6.2 The # operator

The order of evaluation of # and ## operators is unspecified.

If you want the string "34" then use #a#b . If the number is 34 , then a##b . Example:

#include <iostream>
#include <type_traits>

#define DEF_STRING(a,b) #a#b
#define DEF_VALUE(a,b) a##b

int main()
{
    decltype(auto) s = DEF_STRING(3,4);
    static_assert(std::is_same_v<decltype(s), const char (&)[3]>);
    
    auto v = DEF_VALUE(3,4);
    static_assert(std::is_same_v<decltype(v), int>);
}

Additionally, there was such a question on enSO , where a similar case is considered in the comments to the answer: # a ## b . The author, in particular, proposed an amendment to the standard to replace the phrase

The order of evaluation of # and ## operators is unspecified.

on the

The # operator groups with higher precedence than the ## operator.

Because the order of evaluation of preprocessor operators has no observable effect, while precedence and associativity do, but are not reflected in the standard.

In fact, it is proposed to interpret #a##b unambiguously as stringify(a) followed by concatenation with b . Which for the case DEF(3,4) gives "3"4 , i.e. invalid preprocessor token.

At the same time, the result of the macro #a##b can be validated if b is empty or is a suffix of a string literal. Example:

#include <iostream>
#include <string>
using namespace std::string_literals;

#define DEF(a,b) #a##b

int main()
{
    std::cout << DEF(3,s) << '\n';
    std::cout << DEF(3,) << '\n';
}
Scroll to Top