创建一个可以根据参数省略一行的宏

Create a macro that can omit a line based on a parameter

我有以下代码行,由数据库导出程序创建:

typedef struct _s8_VARB
{
    unsigned char _byte[8];
} s8_VARB;

const s8_VARB varb00[] = {
    mMM(1,25,22,12,0,0,0,0,27)
    mMM(0,1,29,12,0,0,0,0,21)
    mMM(1,1,36,12,0,0,0,0,22)
}

mMM 是一个我想定义的宏,其功能将在编译期间产生以下数据:

const s8_VARB varb00[] = {
    1,25,22,12,0,0,0,0,27,
    1,1,36,12,0,0,0,0,22,
}

所以它基本上应该检查第一个参数。如果为 0,则应省略该完整行。如果为1,则所有参数(第1个除外)应为'put on the line',以逗号结尾。

我试过的是这样的:

#define COMMA ,
#define mMM(cond, a,b,c,d,e,f,g,h)  (cond) ? (a),(b),(c),(d),(e),(f),(g),(h) COMMA :

但这不起作用。甚至没有编译,正如 gcc 抱怨的那样:

error: expected expression before ':' token

这个宏定义应该是什么样子的?这在 C 中完全可行吗?

您只能用常量数据初始化数组。根据定义,条件语句不是常量(即使编译器在编译时知道它)。

相反,您可以这样做:

#define _mMM0(...)
#define _mMM1(...)  {__VA_ARGS__},
#define mMM(cond, ...) _mMM##cond(__VA_ARGS__)

const unsigned char varb00[][8] = {
      mMM(1,25,22,12,0,0,0,0,27)
      mMM(0,1,29,12,0,0,0,0,21)
      mMM(1,1,36,12,0,0,0,0,22)
};

我删除了结构并直接用它的唯一成员替换了它。如果 C99 不可用,您可以像以前一样命名每个参数。

这是一个骇人听闻的解决方案。如果参数的数量是固定的并且你不能使用 C99+,那么你可以显式地列出它们而不是使用 ...__VA_ARGS__.

#define mMM(x, ...) mMM##x(__VA_ARGS__)
#define mMM0(...)
#define mMM1(...) __VA_ARGS__,

## 运算符将标记 mMMx 参数粘贴在一起以形成新的宏名称 - mMM0mMM1 - - 然后用剩余的参数调用它。 mMM0() 依次扩展为空,mMM1() 扩展为其参数。

(最后一个元素后的额外尾随逗号不会成为问题。int a[] = { 1, 2, 3, } 是 C 中明确允许的语法。)

作为旁注,调用像

这样的宏
#define m(x) (x) ? 1 : 2

使用例如m(0) 只会将其扩展为 (0) ? 1 : 2。三元运算符不会在预处理器中处理。