C/C++: adding 0

C/C++: adding 0

本文关键字:adding C++      更新时间:2023-10-16

我在函数中有以下一行来计算序列中'G'和'C'的个数:

count += (seq[i] == 'G' || seq[i] == 'C');

编译器是否足够聪明,当它们看到'count += 0'时什么都不做,或者它们实际上浪费了'添加' 0的时间?

一般

x += y;

if (y != 0) { x += y; }

即使是y = 0,因为第一个选项中没有分支。如果它真的很重要,您将不得不检查编译器的输出,但不要认为您的方法更快,因为它有时不执行add。

老实说,谁在乎呢?

[编辑:]这实际上有点有趣。与我最初的假设相反,在未优化的编译中,n += b;优于n += b ? 1 : 0;。然而,通过优化,两者是相同的。更重要的是,这种形式的优化版本总是优于if (b) ++n;,后者总是创建cmp/je指令。(/编辑)

如果您非常好奇,请将以下代码放入编译器并比较生成的程序集!(一定要测试各种优化设置)

int n;
void f(bool b) { n += b ? 1 : 0; }
void g(bool b) { if (b) ++n;     }

我用GCC 4.6.1测试了它:使用g++并且没有优化,g()更短。然而,对于-O3, f()更短:

g():                            f():
    cmpb    $0, 4(%esp)              movzbl  4(%esp), %eax
    je      .L1                      addl    %eax, n
    addl    $1, n
  .L1:
    rep

注意,f()的优化实际上做了您最初写的事情:它实际上是将条件的值添加到n。当然这是在c++中。如果没有bool类型,看看C编译器会怎么做会很有趣。

另一个注意,因为你也标记了这个C:在C中,如果你不使用bool(来自<stdbool.h>),而是使用int s,那么一个版本相对于另一个版本的优势就消失了,因为两个版本现在都必须做一些测试。

这取决于你的编译器,你使用的优化选项和它的优化启发式。此外,在某些体系结构上,为了避免添加0,添加可能比执行条件跳转更快。

编译器不会优化掉+0,除非右边的表达式是一个编译器const值等于0。但是,在所有现代处理器上,添加0比尝试避免添加的分支(如果有的话)要快得多。因此,编译器最终在给定情况下做了最聪明的事情-简单地添加0。

有些人很聪明,有些人不够聪明。它高度依赖于优化器的实现。优化器也可能确定if+慢,所以它仍然会执行加法。