预处理器交换参数

Preprocessor swaps arguments

本文关键字:参数 交换 处理器 预处理      更新时间:2023-10-16

我有一些代码需要一个文本表示的值和一个十六进制表示的值。我两者都需要,但是为了消除潜在的错误来源,我想只指定一次值,并让预处理器处理它。

这是一个项目的例子。

int[]   v = { 0x01, 0x02 };
LPCTSTR s = L"0102";
在这方面,

预处理器连接是一个强大的帮助。下面是相同的代码,但现在通过预处理器命令。

#define STRING2(x) #x
#define STRING(x)  STRING2(x)
#define _S(t) _T(STRING2(t))
#define _H(t) 0x ## t
#define _VS(a,b) _S(a) _S(b)
#define _VH(a,b) _H(a),_H(b)
LPCTSTR s = _VS(01, 02);
int[]   v = { _VH(01, 02) };
预处理器生成的代码如下所示:
int[]   v = { 0x01,0x02 };
LPCTSTR s = L"01" L"02";

但是我仍然在重复我的数据。所以,我试试这个

#define ARGUMENTS 01, 02
LPCTSTR s = _VS(ARGUMENTS);
int[]   v = { _VH(ARGUMENTS) };

现在预处理器代码坏了!

int[]   v = { 0x01, 02,0x };
LPCTSTR s = L"01" L;

请注意,第二个参数和它应该连接的令牌部分被交换或丢失。但是为什么呢?

VS2010帮助页面对我帮助不大。它告诉我,连接运算符在宏展开上添加了约束。这很可能是展开宏ARGUMENTS失败的原因。但我怎么才能让它工作呢?

额外的测试表明,它绝对是阻止宏进一步扩展的连接操作符。所以我需要一种方法来展开参数,然后使用连接运算符。好主意吗?现在怎么样了!

因为ARGUMENTS仍然是单个值,您可以在两个输出中清楚地看到- ARGUMENTS被视为单个参数,然后处理第二个参数(gcc实际上更有帮助,并且扔掉了error: macro "_VS" requires 2 arguments, but only 1 given的预处理)。

要达到你想要的,试试这个:

#define MK_STRING_INT_PAIR(a,b,sname,vname) 
LPCTSTR sname=_VS(a,b); 
int[]   vname={_VH(a,b)};
MK_STRING_INT_PAIR(01,02,s,v)

[编辑]如果需要两个以上的值,可以编写一个简短的程序,在

行中生成一个带有宏的.h文件。
#define MK_PAIRS_2(sname,vname,v0,v1) ...
#define MK_PAIRS_3(sname,vname,v0,v1,v3) ...
#define MK_PAIRS_128(sname,vname,....

生成后,您不需要依赖_VS、_VH帮助宏

(我觉得在c++ 11中有可能使用char[]类型的可变模板和构造函数来实现它,但现在我没有时间去探索它)

我觉得您应该将定义重写为XMacros。这是一种很好的技术,可以让您编写一个包含数据定义的文件(通常具有.def扩展名),如下所示:

VAL(01)
VAL(02)

那么您只需定义一个适当的宏,并包含以获得所需的结构,如:

#define VAL(x) _H(x),
  int[]   v = {
  #include "values.def"
  };
#undef VAL
#define VAL(x) _S(x)
  LPCTSTR s =
    #include "values.def"
  ;
#undef VAL