我可以通过C宏自动收集函数列表吗

我可以通过C宏自动收集函数列表吗,c,gcc,C,Gcc,我想自动收集函数begin FUN\u begin()和FUN\u END()宏的列表,如果我将其编写为: FUN_BEGIN() FUN_DEFINE(f1) { printf("f1\n"); } FUN_DEFINE(f2) { printf("f2\n"); } FUN_DEFINE(f3) { printf("f3\n"); } FUN_END() 代码将展开如下: static bool f1(void) { printf("f1\n");

我想自动收集函数begin FUN\u begin()和FUN\u END()宏的列表,如果我将其编写为:

FUN_BEGIN()

FUN_DEFINE(f1) {
    printf("f1\n"); }

FUN_DEFINE(f2) {
    printf("f2\n"); }

FUN_DEFINE(f3) {
    printf("f3\n"); }

FUN_END()
代码将展开如下:

static bool f1(void) 
{
    printf("f1\n");
}

static bool f2(void)
{
    printf("f2\n");
}


static bool f3(void)
{
    printf("f3\n");
}


void global_fun(void)
{
    f1();
    f2();
    f3();
}

我可以重新简化吗?

一个选项是将定义放在一个单独的文件中

funcs.def

FUN_DEFINE(f1) {
    printf("f1\n"); }

FUN_DEFINE(f2) {
    printf("f2\n"); }

FUN_DEFINE(f3) {
    printf("f3\n"); }
然后在另一个源文件中,执行以下操作

#define FUN_DEFINE(name) static bool name(void)
#include "funcs.def"
#undef FUN_DEFINE

void global_fun(void) {
#define FUN_DEFINE(name) name();
#include "funcs.def"
#undef FUN_DEFINE
}

这种方法有一个名称,但我一时记不起来了。

一种选择是将定义放在一个单独的文件中

funcs.def

FUN_DEFINE(f1) {
    printf("f1\n"); }

FUN_DEFINE(f2) {
    printf("f2\n"); }

FUN_DEFINE(f3) {
    printf("f3\n"); }
然后在另一个源文件中,执行以下操作

#define FUN_DEFINE(name) static bool name(void)
#include "funcs.def"
#undef FUN_DEFINE

void global_fun(void) {
#define FUN_DEFINE(name) name();
#include "funcs.def"
#undef FUN_DEFINE
}

这种方法有一个名字,但我一时记不起来了。

这里有一种方法,它使用构造函数添加到列表中,允许使用您使用的确切语法

#define FUN_BEGIN() struct __fun_list { \
    struct __fun_list *next; \
    bool (*f)(void); \
} *head = NULL; \
static void globals_list_add(bool (*f)(void)) { \
    /* add f to the linked list... */ \
}

#define FUN_DEFINE(f) static bool f(void);\
    static void __attribute__((constructor)) __construct_##f(void) {\
        globals_list_add(f); \
    } \
    static bool f(void)

#define FUN_END() void global_fun(void) { \
    struct __fun_list *cur; \
    for(cur = head; cur; cur = cur->next) { \
        cur->f(); \
    } \
}

注意:构造函数不一定是按照声明的顺序调用的,因此您可能需要在宏中使用
\uuuu LINE\uuuu
根据定义的行号对列表进行排序。

下面是一种使用构造函数添加到列表中的方法,允许使用您使用的确切语法

#define FUN_BEGIN() struct __fun_list { \
    struct __fun_list *next; \
    bool (*f)(void); \
} *head = NULL; \
static void globals_list_add(bool (*f)(void)) { \
    /* add f to the linked list... */ \
}

#define FUN_DEFINE(f) static bool f(void);\
    static void __attribute__((constructor)) __construct_##f(void) {\
        globals_list_add(f); \
    } \
    static bool f(void)

#define FUN_END() void global_fun(void) { \
    struct __fun_list *cur; \
    for(cur = head; cur; cur = cur->next) { \
        cur->f(); \
    } \
}
注意:构造函数不一定按声明顺序调用,因此您可能需要在宏中使用
\uuuu LINE\uuu
按定义的行号对列表进行排序。

替代解决方案:

typedef bool (*func_t) (void);

// ...place function prototypes anywhere in scope

funct_t test_functions [] = 
{
  &f1,
  &f2,
  &f3
};

#define TEST_FUNCTIONS_N (sizeof(test_functions) / sizeof(funct_t))

void global_fun(void)
{
  for(size_t i=0; i<TEST_FUNCTIONS_N; i++)
  {
    test_functions[i]();
  }
}
typedef bool(*func_t)(无效);
//…将功能原型放置在范围内的任何位置
函数测试函数[]=
{
&f1,
&f2,
&f3
};
#定义测试函数(sizeof(测试函数)/sizeof(函数))
void global_fun(void)
{
对于(尺寸i=0;i备选方案:

typedef bool (*func_t) (void);

// ...place function prototypes anywhere in scope

funct_t test_functions [] = 
{
  &f1,
  &f2,
  &f3
};

#define TEST_FUNCTIONS_N (sizeof(test_functions) / sizeof(funct_t))

void global_fun(void)
{
  for(size_t i=0; i<TEST_FUNCTIONS_N; i++)
  {
    test_functions[i]();
  }
}
typedef bool(*func_t)(无效);
//…将功能原型放置在范围内的任何位置
函数测试函数[]=
{
&f1,
&f2,
&f3
};
#定义测试函数(sizeof(测试函数)/sizeof(函数))
void global_fun(void)
{

对于(size_t i=0;i)您考虑的是X-宏。然而,您最终会创建这样的代码,我认为这不是理想的结果:
void global_fun(void){f1(){printf(“f1\n”)}f2(){printf(“f2\n”)}f3(){printf(“f3\n”)}
X-宏的一种描述(不使用该名称)在中找到。好主意!但是全局函数()展开将不正确,它类似于:void global函数{f1();{printf(“f1\n”);}f2();{printf(“f2\n”);}f3();{printf(“f3\n”);}这不是我想要的。啊,是的,函数的其余部分也扩展到其中,这一点很好。你考虑的是X宏。然而,你最终会创建这样的代码,我不认为这是理想的结果:
void global\u fun(void){f1();{printf(“f1\n”)}f2(){printf(“f2\n”)}f3(){printf(“f3\n”)}
X-macros的一个描述(不使用该名称)可以在找到。好主意!但是global_-fun()expand将不正确,它就像:void global_-fun(void){f1(){printf(“f1\n”)}f2(){printf(“f2\n”)}f3(){printf(“f3\n”)}这不是我想要的。啊,是的,函数的其余部分也可以扩展到它。{uu属性__((构造函数))可以在main()之前执行函数,并初始化一个链接,这正是我想要的!我已经测试了代码,完全正常!好主意&谢谢!_属性(构造函数))可以在main()之前执行函数,并初始化一个链接,这正是我想要的!我已经测试了代码,非常有效!好主意&谢谢!编写这样的代码是一个非常糟糕的主意。永远不要使用晦涩的宏重新发明C语言。这将使您的代码不可读、不可维护且容易出错,从而获得零收益。自然而然地,这听起来就像是又一个不必要的C语言没有任何实际问题需要解决的复杂解决方案。我只在我的C单元测试框架中使用它。使用FUN_DEFINE()宏可以自动收集测试()列表函数。所以我可以专注于编写测试函数体,不必考虑在何处以及如何调用它。事实上,我有test nneonneo的答案,它是有效的!你认为它是对的吗?或者你有任何其他建议吗?我的建议是完全使用简单的函数指针数组重写它。对我来说,没有明显的理由让你这么做r需要宏来创建函数列表。发布了替代解决方案,使用100%标准C。编写这样的代码是一个非常糟糕的主意。永远不要使用模糊的宏来重新发明C语言。这将使您的代码不可读、不可维护且容易出错,从而获得零收益。自然而然地,这听起来像是另一个不必要的复杂解决方案没有任何实际问题需要解决。我只在我的C单元测试框架中使用它。使用FUN_DEFINE()宏可以自动收集测试()的列表函数。所以我可以专注于编写测试函数体,不必考虑在何处以及如何调用它。事实上,我有test nneonneo的答案,它是有效的!你认为它是对的吗?或者你有任何其他建议吗?我的建议是完全使用简单的函数指针数组重写它。对我来说,没有明显的理由让你这么做r需要宏来创建函数列表。发布了替代解决方案,使用100%标准C。