【问题标题】:"Unpacking" macro arguments“解包”宏参数
【发布时间】:2021-12-13 20:43:59
【问题描述】:

我有以下宏:

#define HEX 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

#define BITS 0x01

#define ADD_FLAGS(a, b, c, d, e, f, g, h) \
        a, b | BITS, c, d, e, f, g, h

我在某处使用它来创建一个字节数组{ADD_FLAGS(HEX)}。这行不通。 HEX 被解释为 ADD_FLAGS 的单个参数,我收到参数太少的错误。

const myStructure Table[ENTRY_COUNT] =                   
{
   /* Entity Index 0 */
   {
      <some structure fields>,
      ADD_FLAGS(HEX),     // 8-byte array
      <more structure fields>
   }
}

我也尝试了以下变体,但没有成功:

#define EXPAND(x) x
#define ADD_FL(a, b, c, d, e, f, g, h) \
        a, b | BITS, c, d, e, f, g, h
#define ADD_FLAGS(...) ADD_FL EXPAND((__VA_ARGS__))

##################### other variant
#define ADD_FLAGS(...) EXPAND(ADD_FL (__VA_ARGS__))

我正在使用 C99 和三种不同的编译器,因此任何答案都必须符合标准,否则肯定会有编译器无法正常工作(我正在使用 armclang、ghs 和任务)。

【问题讨论】:

  • 是否有理由将它们保留为宏,而不是从中制作适当的函数(或函数模板)?
  • @TedLyngmo 唯一的要求是:HEX 是传递给编译器的编译定义。 BITS 不需要是宏,但值取决于编译定义。数组以 const 结构结束。
  • 您能否展示目标结构以及您希望如何使用宏?它有助于了解最终结果应该是什么。我看到 Staz 在下面做了一个非宏观的回答。如果这不起作用,您能否在该答案下发表评论并描述它不起作用的方式?

标签: c c99


【解决方案1】:

我建议您谨慎使用宏。这是一个 sn-p 示例,它完全按照宏正在执行的操作,但我认为它更合理。

template<typename ... Ts>
constexpr auto add_flags(Ts && ... args){
     std::array flags{std::forward<Ts>(args)...};
     constexpr int bits = 0x01;
     // flags[some_idx] |= bits;
     return flags;
}

【讨论】:

  • 我用我使用的语言变体更新了我的问题。原来我使用的是 C99,甚至不是 C++。这会影响您的回答吗?
  • @kutschkem 嗯,C 和 C++ 是两种不同的语言,这里显示的代码是用 C++ 编写的,而不是 C。请记得添加 only 下次您发布问题时使用适当的标签。
【解决方案2】:

除了强制性的“避免宏”之外,您只需将ADD_FLAGS 包装在另一个宏中。

将其重命名为其他名称,例如ADD_FLAGS_,并添加

#define ADD_FLAGS(...) ADD_FLAGS_(__VA_ARGS__)

这适用于 GCC 和 Clang。在 MSVC 中,这仅适用于新的预处理器(/Zc:preprocessor 标志)。

不知道如何使用旧的 MSVC 预处理器,但由于它出了名的错误,如果可能,我会避免支持它。

【讨论】:

  • “旧的 MSVC”(是)坚定地早于 C99。 __VA_ARGS__ 是 C99 功能。
  • @mlp 旧的预处理器确实支持__VA_ARGS__
  • 这个答案对我来说适用于任务编译器,但我很难让它与 armclang 一起工作(仍然抱怨参数很少,所以评估顺序似乎不同)。自从您声明它适用于clang以来,对此的任何见解。
  • @kutschkem 嗯,工作 here.
  • 我会接受答案,因为它似乎适用于大多数编译器,但我想会在宏之外寻找不同的解决方案。似乎我遇到了特定于编译器的问题:-(也许 armclang 的 keil 实现有差异。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-05
  • 2013-05-03
  • 1970-01-01
  • 2013-11-16
相关资源
最近更新 更多