C 为printf使用_VA_参数
我正在尝试使用C 为printf使用_VA_参数,c,printf,c-preprocessor,C,Printf,C Preprocessor,我正在尝试使用\u VA_ARGS为ASSERT()编写\define。 (此代码适用于不支持所有libc函数的嵌入式处理器) 我的源代码如下: ASSERT(msg == NULL) 头文件中的断言: #define ASSERT(...) if(__VA_ARGS__) { printf("[ASSERT ERROR]" __VA_ARGS__ "\n"); } 预处理器的输出如下,这导致编译错误 if(msg == NULL) { printf("[ASSERT ERROR]" msg
\u VA_ARGS
为ASSERT()
编写\define
。(此代码适用于不支持所有libc函数的嵌入式处理器) 我的源代码如下:
ASSERT(msg == NULL)
头文件中的断言:
#define ASSERT(...) if(__VA_ARGS__) { printf("[ASSERT ERROR]" __VA_ARGS__ "\n"); }
预处理器的输出如下,这导致编译错误
if(msg == NULL) { printf("[ASSERT ERROR]" msg == NULL "\n"); }
如何修复
#define
,在保持代码逻辑正确的同时消除编译错误?没有理由认为这是一个可变宏,至少不需要告诉我们有关您正试图执行的操作的更多信息。使用字符串化操作符#
的简单单参数宏可以很好地完成以下任务:
#define ASSERT(x) if(x); else printf("[ASSERT ERROR] " #x "\n")
还要注意,我省略了结尾处的分号,并将其写成if(x);else
而不是if(!(x))
,以便以下所有代码片段按照预期正确编译,或者按照预期生成编译器错误:
// #1 - this must be an error, no semicolon
ASSERT(x)
// #2 - this must also be an error
ASSERT(x)
else
/*stuff*/ ;
// #3 - the else must go with the first if, not the inner if inside the macro
// expansion
if (x)
ASSERT(y);
else
/*stuff*/ ;
您的原始宏定义未通过上述测试#3。没有理由将其视为可变宏,至少不能告诉我们有关您正试图执行的操作的更多信息。使用字符串化操作符
#
的简单单参数宏可以很好地完成以下任务:
#define ASSERT(x) if(x); else printf("[ASSERT ERROR] " #x "\n")
还要注意,我省略了结尾处的分号,并将其写成if(x);else
而不是if(!(x))
,以便以下所有代码片段按照预期正确编译,或者按照预期生成编译器错误:
// #1 - this must be an error, no semicolon
ASSERT(x)
// #2 - this must also be an error
ASSERT(x)
else
/*stuff*/ ;
// #3 - the else must go with the first if, not the inner if inside the macro
// expansion
if (x)
ASSERT(y);
else
/*stuff*/ ;
您的原始宏定义未通过上面的测试#3。宏的意义是什么?宏的意义是什么?+1,但某些编译器仍会在
if(to)ASSERT(x)上发出虚假的else
警告不幸的是,代码>。对于这种情况,封装在良好的旧do{..}while(false)
规则中。而且没有理由不使用\uu VA\u ARGS\uu
执行宏。有人可能想给它传递一个逗号表达式:)@Jens:没错,有些编译器可能会很挑剔。如果没有必要,可以避免使用\uu VA\u ARGS\uu
,原因之一是它是C99功能,因此不能将它与不支持它作为扩展的C89编译器一起使用。如果您确实想传递逗号表达式,可以在非变量宏中添加一组额外的括号,例如ASSERT((foo,bar))
@Adam Rosenfield谢谢您的建议。在我的代码中我有ASSERT(x)
,我的定义是#define ASSERT(x)if(x){}else{printf(“[ASSERT BUG]”x“\n”)
并且它成功编译。@SudharsanSeshadri:您必须删除该宏中调用printf
时的大括号和分号,否则它可能导致代码编译成功,但却默默地做了错误的事情——这正是我上面示例中的第3种情况。宏很难正确执行(因此).1,但不幸的是,一些编译器仍然会在if(to)ASSERT(x);
上发出虚假的else
警告。对于封装在良好的旧中的这种情况,请执行{..}while(false)
仍然是规则。而且也没有理由不使用\uuuu VA\u ARGS\uuuu
来执行宏。可能有人想给它传递一个逗号表达式:)@Jens:True,有些编译器可能会很挑剔。避免使用\uu VA\u ARGS\uuuu
的一个原因是它是C99功能,因此不能与不支持如果你真的想传递一个逗号表达式,你可以在非变量宏中添加一组额外的括号,例如ASSERT((foo,bar))
@Adam Rosenfield谢谢你的建议。在我的代码中我有ASSERT(x)
,我的定义是\define ASSERT(x)If(x){}else{printf([ASSERT BUG]“\x”\n)
并且它编译成功。@SudharsanSeshadri:您必须删除该宏中对printf
的调用周围的大括号和分号,否则它可能导致代码编译成功,但却默默地做了错误的事情——在我上面的示例中正好是第3种情况。宏很难做到正确(这就是为什么)。