用于Struct成员访问的C99宏扩展

时间:2015-09-25 21:28:55

标签: c macros c99 variadic-macros

是否可以在宏中进行无效检查和访问?

例如:

#define LOG(mystruct, severity, format, ...) ({ \
  severity_t current = ERROR; \
  if (mystruct) { \
    current = mystruct->error_level; \
  } \
  if (severity >= current) { \
   ... //handle logging 
  } \
})

如果我用LOG(NULL, DEBUG, "test %s", "one");打电话给我,我会收到错误:

error: member reference base type 'void' is not a structure or union note: expanded from macro 'LOG' current = mystruct->error_level;

mystruct定义为:

typedef struct mystruct_t {
  severity_t error_level;
}

我想允许使用NULL mystruct。例如:创建结构本身时出错的情况。

2 个答案:

答案 0 :(得分:3)

您的问题是,虽然第一个分支永远不会被采用,但NULL没有正确的类型来执行->error_level

你可以通过给它正确的类型来避免这种情况。我会使用局部变量,而不是强制转换,因此您可以捕获宏的错误用例。只需添加

yourType* myStr = mystruct;
current = myStr->error_level;

你应该没事。

答案 1 :(得分:0)

  

是否可以在宏中进行无效检查和访问?

不,预处理器正在进行简单的文本替换。它不支持宏定义中的条件。

当您使用LOG(NULL, DEBUG, "test %s", "one");的宏时,第四行会扩展为

current = NULL->error_level;

由于NULL通常定义为#define NULL ((void *)0),因此会进一步扩展为

current = ((void *)0)->error_level;

这就是为什么你得到关于void不是结构或联合的消息。

要解决此问题,请不要将NULL传递给宏,将包含NULL的指针传递给宏,例如

mystruct_t *ptr = malloc(...);
if ( !ptr )
    LOG( ptr, DEBUG, "no memory" );