通过宏过度使用进行结构初始化

时间:2010-07-15 20:14:09

标签: c struct macros c-preprocessor stringification

我有一些结构要初始化,手动操作会很繁琐。我想创建一个可以帮助我的宏...但我不确定 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)

或许我应该从其他方面接近它?

3 个答案:

答案 0 :(得分:1)

我之前编写过Python脚本来为我生成这种代码。您可能希望沿着该路线前进,然后将脚本运行到构建过程中。

答案 1 :(得分:0)

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

我想你能得到的最好的东西就像MENU(blah, ITEM(blah,button), NULL, ITEM(blah,display), NULL),你还需要一个单独的原型集,因为缺乏条件扩展。

就个人而言,我会编写一个简单的脚本来生成那种样板代码。一个能理解你所需语法的人。在Python或任何最适合你的地方......

答案 2 :(得分:0)

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

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