c++中的布尔乘法

Boolean multiplication in c++?

本文关键字:布尔乘 c++      更新时间:2023-10-16

考虑以下内容:

inline unsigned int f1(const unsigned int i, const bool b) {return b ? i : 0;}
inline unsigned int f2(const unsigned int i, const bool b) {return b*i;}

f2的语法更紧凑,但是标准是否保证f1f2是严格等价的呢?

此外,如果我希望编译器在编译时知道bi的情况下优化这个表达式,我应该选择哪个版本?

嗯,是的,两者是等价的。bool是整型,true保证在整型上下文中转换为1, false保证在整型上下文中转换为0

(反过来也成立,即非零整数值保证在布尔上下文中转换为true,而零整数值保证在布尔上下文中转换为false)

由于您正在使用无符号类型,因此可以很容易地提出其他可能基于位的但完全可移植的相同内容的实现,例如

i & -(unsigned) b

尽管一个好的编译器应该能够为你的任何版本选择最好的实现。

注:尽管令我非常惊讶的是,GCC 4.1.2几乎完全按照字面意思编译了这三个变体,也就是说,它在基于乘法的变体中使用了机器乘法指令。在?:变体上使用cmovne指令使其无分支是足够聪明的,这很可能使其成为最有效的实现。

是。在表达式中使用true1, false0,这是安全的,并且可以保证:

c++ 11日积分促销,4.5 :

bool类型的右值可以转换为int类型的右值,使用False变为0,true变为1。

编译器将使用隐式转换从b生成unsigned int,所以,是的,这应该可以工作。您通过简单的乘法跳过了条件检查。哪一个更有效/更快?不知道。我认为一个好的编译器很可能会优化这两个版本。

哎呀,下面的代码

inline unsigned int f1(const unsigned int i, const bool b) {return b ? i : 0;}
inline unsigned int f2(const unsigned int i, const bool b) {return b*i;}
int main()
{
    volatile unsigned int i = f1(42, true);
    volatile unsigned int j = f2(42, true);
}

使用gcc -O2编译生成如下程序集:

    .file   "test.cpp"
    .def    ___main;    .scl    2;  .type   32; .endef
    .section    .text.startup,"x"
    .p2align 2,,3
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
LFB2:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $16, %esp
    call    ___main
    movl    $42, 8(%esp)   // i
    movl    $42, 12(%esp)  // j
    xorl    %eax, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE2:

可以看到,f1f2的空间都不大了。

就c++标准而言,编译器可以做任何关于优化的事情,只要它不改变可观察的行为( As if规则)。