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