预处理器交换参数

时间:2016-08-28 14:47:12

标签: c++ visual-studio-2010 c-preprocessor

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

以下是一个项目的例子。

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 help page对我没什么帮助。它告诉我,连接操作符正在限制宏扩展。这很可能是扩大宏观ARGUMENTS正在蓬勃发展的原因。 但是我怎么能让它发挥作用呢?

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

欢迎任何建议。

2 个答案:

答案 0 :(得分:1)

我觉得您应该将您的定义重写为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

答案 1 :(得分:1)

因为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)

[编辑] 如果您需要2个以上的值,请编写一个简短的程序,以生成带有宏的.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 []类型的constexpr-s来做它,但是现在我没有时间去探索它)。