我的C非常生疏,我无法弄清楚这里发生了什么。
#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);
}
输出:
V_PROD_Str(...) = V_FORMAT(13,2,99,44,0)0
xV_PROD_Str(...) = 13.2.9.44.00
我可以看到#x使得文本字符串的内容与“x”相同,但我很好奇##正在做什么以及为什么在创建版本字符串时使用它。
V_PROD_Str后来用作RC文件中的字符串表,而xV_PROD_Str根本没有使用(我根据自己的理解添加了它)
答案 0 :(得分:4)
预处理器##
运算符是标记并置,在问题中使用它是未定义的行为。
与stringify(#
)运算符一样,concatenate运算符处理其参数的未展开值,因此如果您希望它应用于扩展参数,则需要通过另一个宏调用进行间接处理,如同{ {1}}宏,它在对内部宏的调用中扩展其参数。
令牌连接仅在结果是有效令牌时才有效。奇怪的是,xV_Str(x)
是一个有效的预处理数字。但是运算符的实际使用是13.2.9.44.0
,您无法连接) ## 0
和)
。 (你也不想这样做;意图是连接0
的扩展值,但你需要一个间接的宏调用来做到这一点。)
在生成字符串的情况下,标记连接完全没有必要,因为stringify运算符不要求其参数是单个标记。所以以下应该可以正常工作:
V_FORMAT(13,2,9,44,0)