多个__COUNTER__ C

时间:2016-11-09 10:45:52

标签: c macros c-preprocessor counter

我正在玩预处理器和c。试图实现我自己的事件和层次结构系统。 但是我遇到了问题。我试图静态定义我的"模块"可以初始化,以及一些事先也是静态定义的事件。对于我使用 COUNTER 这些非常有效的活动。但我不想混淆模块ID和事件ID。

这是我试图实现的简化版本:

hierarchy.h

project/folder

event.h

#define HIERARCHY_DEFINE(NAME) int hierarchyId = __COUNTER__

的main.c

#define EVENT_REGISTER(NAME) int eventId = __COUNTER__

这将打印出来:

#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)

2 个答案:

答案 0 :(得分:3)

除非您对标识符有其他要求,否则将执行以下操作:

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;
}

答案 1 :(得分:1)

您必须:

  • 在运行时分配ID,
  • 手工分配ids
  • 或将所有事件和模块定义保存在一个位置。

考虑您有a.cb.c,它们分别包含一些EventAEventB定义。由于它们是单独的编译单元,因此编译器无法为它们分配非重叠的ID。正在编译b.c,它甚至不知道还有另一个a.c已经分配了1

对于第一个,有一个RegisterEvent函数,如下所示:

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

并为您需要的每个Event拨打电话。

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

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

拥有所有活动的X列表:

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

现在,在标题中,您将声明所有事件(例如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" };

模块也是如此。