【问题标题】:How to define a function and use it in one macro?如何定义一个函数并在一个宏中使用它?
【发布时间】:2015-07-25 10:43:22
【问题描述】:

我需要定义一个事件处理程序,然后将其添加到某个索引处的处理程序数组中。处理程序永远不会以其真实名称调用,因此我想在一个地方同时处理定义和赋值。一个好的解决方案如下所示:

MAKE_HANDLER(evet_code, my_event) {
    //handle the event
}

我幼稚的解决方案是将其扩展为

void on_my_event(event* ev);
array_of_handlers[event_code] = &on_my_event;
void on_my_event(event* ev) {
    //handle the event
}

显然这是行不通的,因为赋值不能在全局范围内发生(通过常量初始化除外)。我知道我可以让一个宏定义函数,另一个在 main 中分配它,但是当我有许多处理程序时,这将是信息的重复并且使用起来非常乏味。还有哪些其他解决方案?

【问题讨论】:

    标签: c macros


    【解决方案1】:

    您可以创建一个文件,例如 handlers.inc 并将所有宏调用放在那里:

    MAKE_HANDLER(a,b)
    MAKE_HANDLER(c,d)
    MAKE_HANDLER(e,f)
    

    当你使用它时,请执行以下操作:

    #define MAKE_HANDLER(evet_code, my_event) .....
    #include "handlers.inc"
    #undef MAKE_HANDLER
    

    在全局范围内定义 MAKE_HANDLER 只是为了声明和定义。而在初始化函数内部只做初始化。

    【讨论】:

    • 我的包含文件将包含MAKE_HANDLER(a,b) { and some code }。我想主要我可以做#define MAKE_HANDLER(a,b) handlers[a]=...; if (false) 来忽略函数体......
    • 如果你真的需要那里的代码,它会变得更棘手,尽管仍有可能。如果在代码周围添加括号,它可以是宏参数。或者你可以用#ifdef IMPLEMENTATION 之类的东西包围代码。但如果您生成代码,可能会更容易。
    【解决方案2】:

    [...] 因为赋值不能在全局范围内发生 [...]

    您可以使用constructor (search in this page) 在启动时运行分配代码,而不会弄乱您的主要功能:

    void on_my_event(event* ev);
    void on_my_event_constructor(void)  __attribute__((constructor));
    void on_my_event_constructor(void) {
      array_of_handlers[event_code] = &on_my_event;
    }
    void on_my_event(event* ev) {
        //handle the event
    }
    

    虽然这绝不是可移植的。 (但也适用于 GCC 和 clang, apparently with some hacking 也适用于 MSVC。)

    【讨论】:

      猜你喜欢
      • 2012-03-18
      • 2022-10-15
      • 1970-01-01
      • 2022-07-07
      • 2017-09-01
      • 2014-04-17
      • 2019-05-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多