如何在C++中实现可移植的空语句?

43

在C++中,偶尔需要使用一个空语句。例如,在实现assert()时,在非调试配置下禁用它(也请参见此问题):

#ifdef _DEBUG
#define assert(x) if( !x ) { \
                     ThrowExcepion(__FILE__, __LINE__);\
                  } else {\
                     //noop here \
                  }
#else
#define assert(x) //noop here
#endif

到目前为止,我认为正确的方法是使用(void)0;进行无操作:

(void)0;

但是我怀疑它可能会在某些编译器上触发警告 - 例如C4555:表达式没有效果; 预期具有副作用的表达式,在这种特定情况下不会发出Visual C ++警告,但在没有向void进行转换时会发出警告。

它是否普适? 有更好的方法吗?


通常而言,使用基于 DEBUG/RELEASE 的宏来改变程序行为并不是一个好主意... 这样可能会导致调试版本(易于操作)能正常运行,但发布版本却不能。至于无操作(no-op),可以使用 ; 来实现,(void)0;(你的宏中不应包含 ;,这应由调用者自行添加)。 - David Rodríguez - dribeas
@dribeas - David Rodríguez:是的,我知道,但在非调试版本中禁用断言是一种普遍做法,我只是举个例子。 - sharptooth
7
我不明白为什么你需要在一个原本为空的else块中加入一个no-op(空操作)。如果你想以后再填充它,可以将else块保持为空。 - ziu
1
@ziu 更多地是在谈论 #define assert(x) //noop here - AusCBloke
1
@sston - 这并不含糊。C语法规定else与最内层的if相绑定。如果您添加了不正确的缩进,它看起来可能会使人感到含糊不清,但事实并非如此。(一个具有足够高警告设置的编译器可能会声称它是模棱两可的,但在这种情况下,最好的解决方案是将编译器警告调整为您想要编写的代码,或者使用 do { if(!x) ThrowException(__FILE__, __LINE__); } while(0)。) - Chris Lutz
显示剩余5条评论
12个回答

0

据我所知,它是普遍可移植的。

#define MYDEFINE()

也可以尝试这个选项:

将会做得很好。

void noop(...) {}
#define MYDEFINE() noop()

然而,我会坚持使用(void)0或者使用像__noop这样的内部函数。


1
еңЁдҪ иҮӘе·ұзҡ„д»Јз ҒдёӯдҪҝз”Ё#define assertжҳҜжңӘе®ҡд№үиЎҢдёәпјӣж ҮеҮҶ规е®ҡдәҶassertзҡ„еҗ«д№үгҖӮ - James Kanze
1
+1 @JamesKanze 我的意思不是要字面上定义assert name,而是一个用户定义的名称占位符。已澄清。 - mloskot
2
我早有所料,但你永远不知道一些读者会从你纯粹的任意选择中读出什么:-)。 (标准的assert通常使用(void)0,因为它需要可用作子表达式;例如someCondition || assert(otherCondition)。) - James Kanze
@JamesKanze 我完全同意。 - mloskot

0

有很多种方法,这里是我在MSVS2019 cpp编译器中对其中一些方法进行的比较。

__asm {
        nop
       }

在反汇编中,nop 操作需要 1 个机器周期。 do {} while (0); 生成一些指令,需要更多的周期。 简单的 ; 不会生成任何指令。


一个空的do-while循环除非你禁用所有优化,否则将生成0条指令。所以你得到了0条指令,而不是1条指令,这也会导致其他优化变得悲观,因为你的代码不再是C++。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接