我有以下几行代码,由数据库导出程序创建:
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中是否可行?
答案 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__,
##
运算符将标记mMM
和x
参数粘贴在一起以形成新的宏名称 - mMM0
或mMM1
- 其中然后用剩余的参数调用。 mMM0()
反过来扩展为空,mMM1()
扩展为其参数。
(顺便说一下,最后一个元素之后的额外尾随逗号是一个问题。int a[] = { 1, 2, 3, }
在C语言中是明确允许的语法。)
作为旁注,请调用像
这样的宏#define m(x) (x) ? 1 : 2
使用例如m(0)
只会将其展开为(0) ? 1 : 2
。三元运算符不会在预处理器中处理。