我有一些结构需要初始化,手动完成这会很乏味。我想创建一个宏来帮助我......但我不确定 C 预处理器对此已经足够好了。

我有代表菜单的结构。它们仅包含函数指针:

typedef uint8_t (*button_handler) (uint8_t);
typedef void (*pedal_handler) (void);
typedef void (*display_handler) (void);
typedef void (*menu_switch_handler) (void);

#define ON_BUTTON(x) uint8_t menu_frame_##x##_button (uint8_t button)
#define ON_PEDAL(x) void menu_frame_##x##_pedal (void)
#define ON_DISPLAY(x) void menu_frame_##x##_display (void)
#define ON_SWITCH(x) void menu_frame_##x##_switch (void)

typedef struct menu_frame {
   button_handler on_button;
   pedal_handler on_pedal;
   display_handler on_display;
   menu_switch_handler on_switch;
} menu_frame;

这允许我将函数和单独的函数编写为(.c 文件):

ON_BUTTON(blah) { ... }

和菜单(.h 文件):

ON_BUTTON(blah);
ON_DISPLAY(blah);
menu_frame menu_frame_blah = {
   menu_frame_blah_button,
   NULL,
   menu_frame_blah_display,
   NULL
};

有什么方法可以将菜单定义折叠成一个定义吗?我可以做一些可以扩展的事情 MENU(blah, menu_frame_blah_button, NULL, menu_frame_blah_display, NULL) 当然可以,但是有什么办法可以:

  • 使其更短(NULL 或某个名称)
  • 消除需要 ON_BUTTON(...); 从结构之前开始

理想情况下,我想要 MENU(blah, button, NULL, display, NULL) 定义处理程序和菜单结构本身。例如,我不知道如何防止将最后一项扩展到 ON_SWITCH(NULL).

或者也许我应该从其他方式来处理它?

有帮助吗?

解决方案

您无法在 C 中进行条件宏扩展,因此您的宏将根据参数进行不同的扩展,如下所示:不能在宏定义中使用#if。

我想你能得到的最好的就是这样 MENU(blah, ITEM(blah,button), NULL, ITEM(blah,display), NULL), ,并且由于缺乏条件扩展,您仍然需要单独的原型集。

就我个人而言,我会编写一个简单的脚本来生成此类样板 C 代码。一个能够理解您想要的语法的人。使用 Python 或任何最适合你的语言......

其他提示

我之前已经编写过 Python 脚本来生成此类代码。您可能想走这条路,并将脚本应用到您的构建过程中。

您可以单独在预处理器中对条件、有限循环、默认参数和所有此类内容进行编程。Boost 库在其预处理器部分中有一些实现。Boost 主要适用于 C++,但预处理器的内容基本上也应该适用于 C。

通过这些技术,您可以编写复杂但易于使用的宏。使用 C99 而不是 C89 时,实现起来会更简单(您已命名初始化程序和 VA_ARGS),但仍然。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top