在C++中实现无操作语句的便携式方法是什么?
What's a portable way to implement no-op statement in C++?
在C++中偶尔需要一个no-op语句。例如,当实现在非调试配置中禁用的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: expression has no effect; expected expression with side-effect
Visual C++警告,它不是针对这种特定情况发出的,而是在没有转换为void
时发出的。
它是普遍可移植的吗?有更好的方法吗?
最简单的无操作就是根本没有代码:
#define noop
然后用户代码将具有:
if (condition) noop; else do_something();
您提到的另一种选择也是no-op:(void)0;
,但如果您要在宏中使用它,则应该将;
放在一边,让调用者添加:
#define noop (void)0
if (condition) noop; else do_something();
(如果;
是宏的一部分,则会有一个额外的;
(
我怀疑它可能会在一些编译器上触发警告
不太可能,因为((void)0)
是定义NDEBUG
时标准assert
宏扩展到的内容。因此,每当编译包含断言的代码以供发布时,任何为其发出警告的编译器都会发出警告。我预计用户会认为这是一个错误。
我想编译器可以通过为您的提案(void)0
发出警告来避免这个问题,同时只特别处理((void)0)
。所以你最好使用((void)0)
,但我对此表示怀疑
通常,将某物强制转换为void,无论是否使用额外的封闭parens,其惯用含义都是"忽略此项"。例如,在C代码中,它将函数参数强制转换为void
,以抑制对未使用变量的警告。因此,在这一点上,发出警告的编译器也相当不受欢迎,因为抑制一个警告只会给你另一个警告。
请注意,在C++中,允许标准标头相互包含。因此,如果您使用任何标准标头,则assert
可能已由其定义。因此,您的代码在该帐户上是不可移植的。如果您说的是"通用可移植",那么通常应该将任何标准标头中定义的任何宏视为保留标识符。可以取消定义,但为自己的断言使用不同的名称会更明智。我知道这只是一个例子,但我不明白为什么你会想以"通用可移植"的方式定义assert
,因为所有C++实现都已经有了它,而且它并不能实现你在这里定义它的目的。
do { } while(0)
怎么样?是的,它添加了代码,但我相信现在大多数编译器都能够对其进行优化。
;被视为标准no-op。请注意,编译器可能不会从中生成任何代码。
我认为这里的目标,以及不将宏定义为空的原因,是要求用户添加;
。为此,在语句合法的任何地方,(void)0
(或((void)0)
,或其其他变体(都可以。
我发现这个问题是因为我需要在全局范围内做同样的事情,在这里,一个简单的旧语句是非法的。幸运的是,C++11为我们提供了一个替代方案:static_assert(true, "NO OP")
。这可以在的任何位置使用,并实现了我在宏之后需要;
的目标。(在我的例子中,宏是解析源文件的代码生成工具的标记,因此当将代码编译为C++时,它将始终是一个NO-OP。(
我来晚了,但在Arduino项目中的loop((中,所有处理都是在定时器中断服务例程(ISR(中完成的。发现内联汇编程序代码在没有定义函数的情况下对我有效:
void loop(){
__asm__("nopnt"); // Do nothing.
}
我建议使用:
static_cast<void> (0)
关于
#define NOP() ({(void)0;})
或者只是
#define NOP() ({;})
AFAIK,它是通用的可移植性。
#define MYDEFINE()
也一样。
另一种选择可能是这样的:
void noop(...) {}
#define MYDEFINE() noop()
然而,我会坚持使用(void)0
或使用像__noop 这样的内部函数
inline void noop( ) {}
自记录
优化不会省略此代码
static void nop_func() { }
typedef void (*nop_func_t)();
static nop_func_t nop = &nop_func;
for (...)
{
nop();
}
有很多方法,下面是我在MSVS2019Cpp编译器中对其中一些方法进行的比较。
__asm {
nop
}
拆卸时转换为nop
操作,需要1个机器循环。CCD_ 26生成一些指令。简单的;
不会生成任何内容。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 以C++读取文件并处理可能的错误的便携式方法
- GCC 7,-隐式故障警告,以及清除它们的便携式方法
- 有没有一种便携式方法可以在 C/C++ 中生成 nop 操作码?
- "永远"阻止线程的最简单便携式方法是什么?
- C 便携式方法获取u8字符串文字的值表示
- 是否有一种便携式/标准的方法可以在堆栈跟踪中获取文件名和亚麻布
- 使用 boost::asio 是一种便携式方法来查找可用端口号
- 在 C++11 中设置 std::线程优先级的便携式方法
- 在没有警告(或编译指示)的情况下进行便携式"assign within conditional expressions"的好方法?
- 检查长类型数据是否在 int 范围内的便携式方法是什么?
- 在C++中实现无操作语句的便携式方法是什么?
- 用sprintf打印十六进制值的便携式方法