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

时间:2015-03-19 23:38:36

标签: c gcc c-preprocessor

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

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个除外)都应放在第39行,以逗号结尾。

我试过的是:

#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中是否可行?

2 个答案:

答案 0 :(得分:6)

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

相反,你可以这样做:

#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不可用,您可以像以前一样为每个参数命名。

答案 1 :(得分:4)

这是一个hackish解决方案。如果参数的数量是固定的并且您无法使用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。三元运算符不会在预处理器中处理。