即使条件语句块中没有有效语句,是否会对条件语句进行求值?如果是,如何优化代码以便在这种情况下不评估条件语句? 例如:
if( get_value() !=NULL)
{
}
或
if( get_value() != NULL)
{
do{}while(0);
}
在多个地方,在现有项目中,只是为了获得调试打印,有这样的检查。使用宏函数可以使打印无效,但如何优化条件语句?手动删除这些比较非常困难
答案 0 :(得分:1)
C和C ++标准要求编译器确保get_value()
被评估(或者至少表现为 as as if 它被评估)。
因此,在一般情况下,将评估get_value
。您可以轻松查看with godbolt:
extern int* get_value();
int func() {
if( get_value() !=NULL)
{
}
}
在gcc 4.4.7上生成x86程序集,如下所示:
sub rsp, 8
call get_value()
add rsp, 8
ret
请注意,get_value()
被调用,但是!= NULL检查没有发生,因为该比较是不可观察的。所以对于这个编译器,你可以说严格意义上没有评估完整的比较,但是由于get_value
仍然必须被调用(这可能是昂贵的部分),因此没有完全消除比较。
编译器被迫采用这条路径,因为它不知道get_value
可能有什么副作用,所以它必须调用它。可以忽略返回值,因为它知道比较和空if语句体没有效果。
然而,在一个特殊情况下,编译器可以消除整个语句 - 如果它可以在编译时证明get_value
方法没有副作用。如果在同一个编译单元中声明了get_value方法(也许还有一些奇特的链接时优化),那么这是可能的。
我们更新示例以将get_value的实现放在编译单元中,并确保它没有副作用:
int* get_value() {
return 0;
}
int func() {
if( get_value() !=NULL)
{
}
}
现在,该方法为compiled into a no-op:
func():
rep
ret
(对于那个显然无用的rep前缀的功能,see here ...)
所以这一切都取决于get_value
的细节,以及编译器在编译空if语句时可以知道多少。