多个__COUNTER__ C

Multiple __COUNTER__ C

我正在研究预处理器和 c。尝试实现我自己的事件和层次结构系统。 但是我遇到了一个问题。我正在尝试静态定义可以初始化的 "modules",以及一些预先静态定义的事件。对于我使用的事件,COUNTER 效果很好。但我不想混淆模块 ID 和事件 ID。

我想要实现的目标的简化版本:

hierarchy.h

#define HIERARCHY_DEFINE(NAME) int hierarchyId = __COUNTER__

event.h

#define EVENT_REGISTER(NAME) int eventId = __COUNTER__

main.c

#include "event.h"
#include "hierarchy.h"

EVENT_REGISTER(EventOne);
HIERARCHY_DEFINE(ModuleOne);
EVENT_REGISTER(EventTwo);

int main(void){
    printf("events(%d, %d) modules(%d)\n",EventOne,EventTwo,ModuleOne);
    return 1;
}

这将打印出:

events(0, 2) modules(1)

当我试图达到:

events(0, 1) modules(0)

我环顾四周,有人说我无法自己创建计数器。看到了升压计数器,但这也没有达到我想要的效果。

有人知道我该如何处理这种情况吗?

谢谢!

编辑:

对我的代码的实际外观略作修改

struct Event{
    uint8_t eventId;
    uint8_t * data;
    const char * description;
};

#define EVENT_REGISTER(eventName, desc)\
static Event eventName = {.eventId = __COUNTER__, .data = 0, .description = desc }




EVENT_REGISTER(Timer_5, "Timer 5 hZ");

除非您对标识符有额外的要求,否则可以执行以下操作:

definitions.inc

EVENT_REGISTER(Timer_5, "Timer 5 Hz")
EVENT_REGISTER(Timer_10, "Timer 10 Hz")
MODULE_REGISTER(Module_SSH)
MODULE_REGISTER(Module_NCO)
#undef EVENT_REGISTER
#undef MODULE_REGISTER

app.c

#define EVENT_REGISTER(a, d) a,
#define MODULE_REGISTER(a)
enum events {
#include "definitions.inc"
};

#define EVENT_REGISTER(a, d)
#define MODULE_REGISTER(a) a,
enum modules {
#include "definitions.inc"
};

struct Event {
    uint8_t event_id;
    uint8_t *data;
    const char *description;
};

#define MODULE_REGISTER(a)
#define EVENT_REGISTER(a, d) static struct Event Event_##a = { .event_id = a, \
    .data = NULL, \
    .description = d \
};
#include "definitions.inc"


int main (int argc, char **argv)
{
    printf("events(%d, %d) modules(%d)\n", Timer_10, Timer_5, Module_SSH);

    return EXIT_SUCCESS;
}

您必须:

  • 在运行时分配 ID,
  • 手动分配 ID
  • 或者将所有事件和模块定义放在一个地方。

假设您有 a.cb.c,它们分别包含一些 EventAEventB 定义。由于它们是独立的编译单元,编译器无法为它们分配 non-overlapping id。编译 b.c,它甚至不知道还有另一个 a.c 已经分配了 id 1

对于第一个,有一个像这样的 RegisterEvent 函数:

void RegisterEvent(Event* event){
  static int nextEventId = 0;
  event->eventId = nextEventId;
}

并为您需要的每个 Event 调用它。

第二个很明显,但是乏味且容易出错。

对于第三种解决方案,您可以使用X macro

X-list 您的所有活动:

#define EventList \
  Event(FirstEvent, "FirstEvent") \
  Event(Timer_1, "Timer 1 hZ") \
  ... 
  Event(Timer_5, "Timer 5 hZ")

现在,在 header 中您要声明所有事件(例如,events.h):

#define Event(name, desc) EventID ## name,
enum EventID{
 EventIDZero = 0,
 EventList 
 EventIDCount
};
#undef Event

#define Event(name, desc) \
  extern Event name;
EventList
#undef Event

并且在您的事件定义所在的单个编译单元中(例如,events.c):

#include "events.h"

#define Event(name, desc) \
  Event name = {.eventId = EventID ## name, .data = 0, .description = desc };
EventList
#undef Event

宏扩展后,events.c 看起来像(为了便于阅读而略作编辑):

enum EventID{
 EventIDZero = 0,
 EventIDFirstEvent, EventIDTimer_1, EventIDTimer_5,
 EventIDCount
};

extern Event FirstEvent; 
extern Event Timer_1; 
extern Event Timer_5;

Event FirstEvent = {.eventId = EventIDFirstEvent, .data = 0, .description = "FirstEvent" }; 
Event Timer_1 = {.eventId = EventIDTimer_1, .data = 0, .description = "Timer 1 hZ" }; 
Event Timer_5 = {.eventId = EventIDTimer_5, .data = 0, .description = "Timer 5 hZ" };

模块也是如此。