结构成员访问的 C99 宏扩展
C99 Macro Expansion for Struct Member Access
是否可以在宏中进行无效检查和访问?
例如:
#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
的可能性。例如:创建结构本身时出现错误的情况。
你的问题是虽然第一个分支永远不会被采用,NULL
没有正确的类型来做 ->error_level
。
你可以通过给它正确的类型来避免这种情况。我会用局部变量而不是强制转换来做到这一点,这样您就可以捕获宏的错误用例。只需添加
yourType* myStr = mystruct;
current = myStr->error_level;
你应该没问题。
Is it possible to do a nullity check and an access in a macro?
不,预处理器正在执行简单的文本替换。它不支持宏定义中的条件。
当您将宏与 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" );
是否可以在宏中进行无效检查和访问?
例如:
#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
的可能性。例如:创建结构本身时出现错误的情况。
你的问题是虽然第一个分支永远不会被采用,NULL
没有正确的类型来做 ->error_level
。
你可以通过给它正确的类型来避免这种情况。我会用局部变量而不是强制转换来做到这一点,这样您就可以捕获宏的错误用例。只需添加
yourType* myStr = mystruct;
current = myStr->error_level;
你应该没问题。
Is it possible to do a nullity check and an access in a macro?
不,预处理器正在执行简单的文本替换。它不支持宏定义中的条件。
当您将宏与 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" );