c ++中的布尔乘法?

时间:2012-12-25 22:37:24

标签: c++ boolean ternary-operator standards-compliance

请考虑以下事项:

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时优化此表达式,我更喜欢哪个版本?

4 个答案:

答案 0 :(得分:11)

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

(反过来也是如此,即保证非零整数值在布尔上下文中转换为true,而保证零整数值在布尔上下文中转换为false。)< / p>

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

i & -(unsigned) b

虽然一个不错的编译器应该能够为你的任何版本选择最好的实现。

P.S。虽然令我惊讶的是,GCC 4.1.2几乎字面上编译了所有三个变体,即它在基于乘法的变体中使用了机器乘法指令。它足够聪明,可以在cmovne变体上使用?:指令使其无分支,这很可能使其成为最有效的实现。

答案 1 :(得分:6)

是。假设true 1 false0 {{1}}在表达式中使用时可以安全地保证:

C ++ 11,积分促销,4.5

  

bool类型的rvalue可以转换为int类型的rvalue   假成为零,真正成为一个。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

FWIW,以下代码

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 ++标准而言,允许编译器对优化做任何事情,只要它不改变可观察行为(就好像规则)。