c++ - 如何定义递归可变参数宏?

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

我正在尝试将代表信号总线位的 bool 值转换为整数。我正在使用以下结构:

#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 : '<<'

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

最佳答案

显然,对于包含多个逗号分隔参数的 __VA_ARGS__ 的递归扩展,MS VC++ 的行为与预期不同。在嵌套宏中展开时,编译器将整个 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 .

关于c++ - 如何定义递归可变参数宏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36925989/

相关文章:

c - C 中的 __attribute__ 或类似的东西是什么?

c - C 结构中的默认值

c# - 无法在 VS2012 上安装 HtmlAgilityPack

excel - 如何使用 Visual Studio 工具集检测 VSTO 插件 (Excel)?

c++ - 不调用 mouseReleaseEvent

c++ - 如何从 vector 中删除所有项目? C++

c++ - 如果 null 不是有效值,则使参数成为引用而不是指针

c++ - 显示图像时在最小化/最大化期间保持纵横比?

c++ - 将 C 源图像转储转换为原始图像

git - 克隆成功但 check out 失败