bia*_*lix 44 c c++ macros compiler-warnings visual-c++
由于本答案中描述的原因,我经常在我的#defines中使用do-while(0)构造.此外,我正在尝试使用尽可能高的编译器警告级别来捕获更多潜在问题,并使我的代码更加健壮和跨平台.所以我通常使用-Wall
gcc和/Wall
MSVC.
不幸的是,MSVC抱怨do-while(0)构造:
foo.c(36) : warning C4127: conditional expression is constant
Run Code Online (Sandbox Code Playgroud)
我应该怎么做这个警告?
只是为所有文件全局禁用它?对我来说这似乎不是一个好主意.
Pav*_*sky 45
简介:在这种特殊情况下,此警告(C4127)是一个微妙的编译器错误.随意禁用它.
深入:
它的目的是捕获逻辑表达式在非显而易见的情况下评估为常量的情况(例如if(a==a && a!=a)
,在某种程度上,它转变为while(true)
其他有用的构造变为无效.
for(;;)
如果您想要启用此警告,Microsoft建议使用无限循环,并且您的案例没有解决方案.这是我公司的开发惯例允许禁用的极少数Level-4警告之一.
Eri*_*nen 28
也许你的代码需要更多的猫头鹰:
do { stuff(); } while (0,0)
Run Code Online (Sandbox Code Playgroud)
或者较少上镜而且警告产生较少:
do { stuff(); } while ((void)0,0)
Run Code Online (Sandbox Code Playgroud)
Mic*_*ter 17
正如Michael Burr在Carl Smotricz的回答中所说,对于Visual Studio 2008+,您可以使用__pragma:
#define MYMACRO(f,g) \
__pragma(warning(push)) \
__pragma(warning(disable:4127)) \
do { f; g; } while (0) \
__pragma(warning(pop))
Run Code Online (Sandbox Code Playgroud)
\
如果您希望宏不可读,可以将它放在一行(没有s).
nev*_*lis 15
我有一个模式,我基于这里的答案,它适用于clang,gcc和MSVC.我在这里发帖,希望它对其他人有用,因为这里的答案帮助我制定它.
#ifdef WIN32
# define ONCE __pragma( warning(push) ) \
__pragma( warning(disable:4127) ) \
while( 0 ) \
__pragma( warning(pop) )
#else
# define ONCE while( 0 )
#endif
Run Code Online (Sandbox Code Playgroud)
我这样使用它:
do {
// Some stuff
} ONCE;
Run Code Online (Sandbox Code Playgroud)
您也可以在宏中使用它:
void SomeLogImpl( const char* filename, int line, ... );
#ifdef NDEBUG
# define LOG( ... )
#else
# define LOG( ... ) do { \
SomeLogImpl( __FILE__, __LINE__, __VA_ARGS__ ); \
} ONCE
#endif
Run Code Online (Sandbox Code Playgroud)
如果F在函数中使用'ONCE',这也适用于上面指出的情况:
#define F( x ) do { f(x); } ONCE
...
if (a==b) F(bar); else someFunc();
Run Code Online (Sandbox Code Playgroud)
编辑:多年以后,我意识到我忘了添加我实际编写这个宏的模式 - "switch-like-a-goto"模式:
do {
begin_some_operation();
if( something_is_wrong ) {
break;
}
continue_big_operation();
if( another_failure_cond ) {
break;
}
finish_big_operation();
return SUCCESS;
} ONCE;
cleanup_the_mess();
return FAILURE;
Run Code Online (Sandbox Code Playgroud)
这给你一个try/finally-ish结构,它比你的清理和返回代码更加结构化.使用此ONCE宏而不是while(0)将关闭VS.
小智 5
使用较新版本的 MS 编译器,您可以使用警告抑制:
#define MY_MACRO(stuff) \
do { \
stuff \
__pragma(warning(suppress:4127)) \
} while(0)
Run Code Online (Sandbox Code Playgroud)
您也可以推送/禁用/弹出,但抑制是一种更方便的机制。