Preet Sangha
Preet Sangha

Reputation: 65556

What's the difference in the # and ## in the following C code?

My C is very rusty and I can't really work out what is happening here.

#define V_Str(x)                    #x
#define V_FORMAT(a,b,c,d,e)         a ## . ## b ## . ## c ## . ## d ## . ## e 
#define V_PROD_STR                  V_Str(V_FORMAT(13,2,99,44,0) ## 0)

#define xV_Str(x)                   V_Str(x)
#define xV_PROD_STR                 xV_Str(V_FORMAT(13,2,9,44,0) ## 0)

void Test()
{
    printf(" V_PROD_Str(...) = %s\n", V_PROD_STR);
    printf("xV_PROD_Str(...) = %s\n", xV_PROD_STR);
}

output:

 V_PROD_Str(...) = V_FORMAT(13,2,99,44,0)0
xV_PROD_Str(...) = 13.2.9.44.00

I can see that the #x makes the contents of makes a literal string the same as "x", but I'm curious as to what ## is doing and why it's being used int he creation of the version string.

The V_PROD_Str is later used as in string tables in RC files, while xV_PROD_Str is not used at all (I added it for my own understanding)

Upvotes: 1

Views: 1526

Answers (1)

rici
rici

Reputation: 241901

The preprocessor ## operator is token concatenation, and the use of it in the question is Undefined Behaviour.

Like the stringify (#) operator, the concatenate operator works on the unexpanded value of its arguments, so if you want it to apply to expanded arguments you need to indirect through another macro call, as with the xV_Str(x) macro, which expands its argument in the call to the inner macro.

Token concatenation will only work if the result is a valid token. Oddly, 13.2.9.44.0 is a valid preprocessing number. But the actual use of the operator is ) ## 0, and you cannot concatenate ) and 0. (Nor did you want to; the intent was to concatenate the expanded value of V_FORMAT(13,2,9,44,0) but you'd need an indirect macro call to do that.)

In the case of producing strings, token concatenation is completely unnecessary, since the stringify operator does not require its argument to be a single token. So the following should work fine:

#define V_Str(x)                    #x
#define xV_Str(x)                   V_Str(x)
#define V_FORMAT(a,b,c,d,e)         a.b.c.d.e
#define V_PROD_STR                  xV_Str(V_FORMAT(13,2,99,44,0)0)

Upvotes: 4

Related Questions