简体   繁体   English

C99宏扩展用于结构成员访问

[英]C99 Macro Expansion for Struct Member Access

Is it possible to do a nullity check and an access in a macro? 是否可以在宏中进行无效检查和访问?

Eg: 例如:

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

If I call this with LOG(NULL, DEBUG, "test %s", "one"); 如果我用LOG(NULL, DEBUG, "test %s", "one");调用它LOG(NULL, DEBUG, "test %s", "one"); I get an error as such: 我收到这样的错误:

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

mystruct is defined as: mystruct定义为:

typedef struct mystruct_t {
  severity_t error_level;
}

I want to allow the possibility of working with a NULL mystruct . 我想允许使用NULL mystruct的可能性。 Eg: case of when there is an error creating the structure itself. 例如:创建结构本身出错时的情况。

Your problem is that although the first branch will never been taken, NULL hasn't the correct type to do a ->error_level . 您的问题是,尽管永远不会采用第一个分支,但NULL不是执行->error_level的正确类型。

You can avoid that by giving it the right type. 您可以通过为其指定正确的类型来避免这种情况。 I would do that with a local variable, not a cast so you'd capture wrong use cases of your macro. 我会使用局部变量而不是强制类型转换来执行此操作,因此您将捕获宏的错误用例。 Just add 只需添加

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

and you should be fine. 你应该没事的

Is it possible to do a nullity check and an access in a macro? 是否可以在宏中进行无效检查和访问?

Nope, the preprocessor is doing simple text replacement. 不,预处理程序正在执行简单的文本替换。 It doesn't support conditionals inside the definition of a macro. 它不支持宏定义内的条件。

When you use the macro with LOG(NULL, DEBUG, "test %s", "one"); 当您将宏与LOG(NULL, DEBUG, "test %s", "one"); , the fourth line expands to ,第四行扩展为

current = NULL->error_level;

and since NULL is typically defined as #define NULL ((void *)0) , that further expands to 并且由于通常将NULL定义为#define NULL ((void *)0) ,因此它进一步扩展为

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

which is why you get the message about void not being a structure or union. 这就是为什么您会收到有关void不是结构或联合的信息的原因。


To fix the problem, don't pass NULL to the macro, pass the pointer that contains NULL to the macro, eg 要解决此问题,请不要将NULL传递给宏,而应将包含NULL的指针传递给宏,例如

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM