我想做以下事情:
F_BEGIN
F(f1) {some code}
F(f2) {some code}
...
F(fn) {some code}
F_END
并生成以下内容
int f1() {some code}
int f2() {some code}
...
int fn() {some code}
int (*function_table)(void)[] = { f1, f2, ..., fn };
功能本身很简单。我似乎无法做的是跟踪函数表的所有名称,直到结束。
我看了this question和this question,但我无法为我工作。 有什么想法吗?
答案 0 :(得分:14)
使用预处理器执行此操作的常规方法是定义宏中的所有函数,这些函数将另一个宏作为参数,然后使用其他宏来提取所需的内容。以你的例子:
#define FUNCTION_TABLE(F) \
F(f1, { some code }) \
F(f2, { some code }) \
F(f3, { some code }) \
:
F(f99, { some code }) \
F(f100, { some code })
#define DEFINE_FUNCTIONS(NAME, CODE) int NAME() CODE
#define FUNCTION_NAME_LIST(NAME, CODE) NAME,
FUNCTION_TABLE(DEFINE_FUNCTIONS)
int (*function_table)(void)[] = { FUNCTION_TABLE(FUNCTION_NAME_LIST) };
答案 1 :(得分:5)
如果您有C99兼容编译器,则预处理器具有可变长度参数列表。 P99有一个预处理器P99_FOR
可以执行“代码展开”,就像你想要实现的那样。为了贴近你的榜样
#define MYFUNC(DUMMY, FN, I) int FN(void) { return I; }
#define GENFUNCS(...) \
P99_FOR(, P99_NARG(__VA_ARGS__), P00_IGN, MYFUNC, __VA_ARGS__) \
int (*function_table)(void)[] = { __VA_ARGS__ }
GENFUNCS(toto, hui, gogo);
将扩展为以下(未经测试)
int toto(void) { return 0; }
int hui(void) { return 1; }
int gogo(void) { return 2; }
int (*function_table)(void)[] = { toto, hui, gogo };
答案 2 :(得分:2)
有一个叫X Macro的东西,它用作:
一种可靠维护代码或数据的并行列表的技术,其相应项必须以相同顺序出现
它是这样工作的:
#include <stdio.h>
//you create macro that contains your values and place them in (yet) not defined macro
#define COLORS\
X(red, 91)\
X(green, 92)\
X(blue, 94)\
//you can name that macro however you like but conventional way is just an "X"
//and then you will be able to define a format for your values in that macro
#define X(name, value) name = value,
typedef enum { COLORS } Color;
#undef X //just another convention (so you don't use it accidentally, I think)
int main(void)
{
#define X(name, value) printf("%d, ", name);
COLORS
#undef X
return 0;
}
您的问题的解决方案是:
#define FUNCTIONS \
F(f1, code1)\
F(f2, code2)\
F(f3, code3)
#define F(name, code) int name(void){code}
FUNCTIONS
#undef F
#define F(name, code) &name,
int (*function_table[])(void) = { FUNCTIONS };
#undef F
答案 3 :(得分:1)
这是对CPP的滥用,但却是一种常见的滥用行为。我处理情况 像这样定义虚拟宏
#define FUNCTIONS \
foo(a,b,c,d) \
foo(a,b,c,d) \
foo(a,b,c,d)
now,
#define foo(a,b,c,d) \
a+b ;
FUNCTIONS
#undef foo
之后,当您想要使用相同列表完成不同的事情时
#define foo(a,b,c,d) \
a: c+d ;
FUNCTIONS
#undef foo
它有点难看和繁琐,但它确实有效。
答案 4 :(得分:0)
Boost是一个C ++库,但它的预处理器模块仍然适合在C中使用。它提供了一些令人惊讶的高级数据类型和功能,可用于预处理器。你可以看一下。