【问题标题】:How to define recursive variadic macros?如何定义递归可变参数宏?
【发布时间】:2016-04-28 21:41:54
【问题描述】:

我正在尝试将表示信号总线位的布尔值转换为整数。我正在使用以下构造:

#define B_TO_UINT1(b00)      (((uint32_t) b00 << 0))
#define B_TO_UINT2(b01, ...) (((uint32_t) b01 << 1) | B_TO_UINT1(__VA_ARGS__))
#define B_TO_UINT3(b02, ...) (((uint32_t) b02 << 2) | B_TO_UINT2(__VA_ARGS__))
#define B_TO_UINT4(b03, ...) (((uint32_t) b03 << 3) | B_TO_UINT3(__VA_ARGS__))
// ...

使用宏级联转换1、2、3位总线时,前2位都可以,但是3位转换报错:

cmd = B_TO_UINT1(1);          // line_1
cmd = B_TO_UINT2(1, 0);       // line_2
cmd = B_TO_UINT3(0, 1, 1);    // line_3

line_3 上的构建错误:

warning C4003: not enough actual parameters for macro 'B_TO_UINT1'

error C2059: syntax error : '&lt;&lt;'

所以,看起来__VA_ARGS__ 部分没有通过递归正确扩展。真的是这样吗?如果是这样,是否有解决方法?

【问题讨论】:

  • bxx的东西放在括号里。
  • @EugeneSh。 - 谢谢。通常是一个很好的提示,但它不能解决这个特定的问题(我得到了其他,) 相关的错误消息)。无论如何,在实际代码中,由于其他原因,我不能使用括号。
  • ".. 无论如何,在实际代码中,由于其他原因我不能使用括号.." 在这种情况下,代码有一些问题。无论如何,你收到什么信息?
  • 顺便说一句,无法重现:ideone.com/8BHOi4

标签: c++ c visual-studio-2012 macros variadic-macros


【解决方案1】:

显然,MS VC++ 的行为与预期的不同,因为 __VA_ARGS__ 的递归扩展包含多个逗号分隔的参数。在嵌套宏中展开时,编译器会将整个 arg 列表视为一个参数。

例子也可以看herehere

但是,@Ise Wisteria 建议使用 EXPAND(x) 宏作为解决方法。使用这个技巧,我将代码更改为:

#define EXPAND( x ) x
#define B_TO_UINT1(b00)      (((uint32_t) b00 << 0))
#define B_TO_UINT2(b01, ...) (((uint32_t) b01 << 1) | EXPAND( B_TO_UINT1(__VA_ARGS__)))
#define B_TO_UINT3(b02, ...) (((uint32_t) b02 << 2) | EXPAND( B_TO_UINT2(__VA_ARGS__)))
#define B_TO_UINT4(b03, ...) (((uint32_t) b03 << 3) | EXPAND( B_TO_UINT3(__VA_ARGS__)))
// ...

现在构建错误已消除。

注意:我没有明确地说“一个错误”,b/c 可能有一个地方可以理解标准的 MS 方式,如 here 所述。

【讨论】:

    猜你喜欢
    • 2012-01-04
    • 2012-05-22
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多