【问题标题】:Help with 2 C macros帮助 2 个 C 宏
【发布时间】:2010-07-11 17:52:58
【问题描述】:

我定义了 2 个宏:

#define HCL_CLASS(TYPE) typedef struct TYPE { \
                          HCLUInt rc; \
                          void (*dealloc)(TYPE*);

#define HCL_CLASS_END(TYPE) } TYPE; \
TYPE * TYPE##Alloc() { TYPE *ptr = (TYPE *)malloc(sizeof(TYPE)); if (ptr != NULL) ptr->rc = 1; return ptr; }

这些宏的目的是创建一个带有一些预定义成员(保留计数和解除分配器)函数的 C 结构体,并自动创建一个分配器函数。

现在,当我像这样使用这些宏时:

HCL_CLASS(Dummy)
int whatever;
HCL_CLASS_END(Dummy)

他们被扩展成这个(直接取自 XCode):

typedef struct Dummy { HCLUInt rc; void (*dealloc)(Dummy*);

int whatever;

} Dummy; Dummy * DummyAlloc() { Dummy *ptr = (Dummy *)malloc(sizeof(Dummy)); if (ptr != ((void *)0)) ptr->rc = 1; return ptr; }

当我尝试编译这个时,我得到两个错误:

  • 调用 HCL_CLASS 的行上的“预期 ')' 在 '*' 标记之前”
  • “预期为 ';'在声明 int 结构成员的行的“int”之前

我看不出这些错误的原因。如果你能帮我找到它,我将不胜感激。谢谢。

【问题讨论】:

  • 只是一个通用的样式类型,不要强制转换 malloc()。这样做可以隐藏潜在的问题。例如,假设您忘记包含 stdlib.h,因此假设 malloc() 返回 int。如果 sizeof(int) 和 sizeof(Dummy) 大小不同,您可以想象随之而来的破损。唯一需要强制转换的情况是,如果您与 C++ 混合,不这样做会导致错误。 C 在没有强制转换的情况下非常高兴,因为 malloc 返回一个指向某物的指针,而不是任何特定的东西。
  • 你的意思是 sizeof(Dummy *) 但我 +1 你是正确的。
  • 是的,我有,键没有按下,我的错误:)

标签: c macros struct


【解决方案1】:

你需要使用struct作为dealloc的参数,而不是typedef:

#define HCL_CLASS(TYPE) typedef struct _##TYPE { \
                          HCLUInt rc; \
                          void (*dealloc)(struct _##TYPE*);  
                       /* use struct here ^^^^^^, not the typedef */

#define HCL_CLASS_END(TYPE) } TYPE; \
TYPE * TYPE##Alloc() { TYPE *ptr = (TYPE *)malloc(sizeof(TYPE));\
                       if (ptr != NULL) ptr->rc = 1; return ptr; }

这是因为你声明 dealloc 的地方的 typedef 不完整。

另外,在 C++ 中,你的结构名称和 typedef 不能冲突。所以我通过_##TYPE在结构名称中添加了一个下划线。

【讨论】:

  • 谢谢,有帮助。只要*允许我这样做,我就会接受这个答案是正确的:)
  • 很高兴听到这个消息。如果您在 C 模式下使用非常严格的编译器,则还必须区分结构名称和 typedef 名称。
  • 实际上,struct 和 typedef 名称 可以 在 C 中“冲突”,尽管我很确定 C++ 要求它们是不同的。
  • @David X 你是对的,我的情况正好相反。为后代编辑。