这两个陈述有什么区别?

Hai*_*iri -3 c

int a = 5;
int b = 6;
int c;
Run Code Online (Sandbox Code Playgroud)

第一份声明:

c = a > b ? 1 : 0;
Run Code Online (Sandbox Code Playgroud)

第二声明:

c = (a > b);
Run Code Online (Sandbox Code Playgroud)

上面两个有什么区别?

Ant*_*ala 8

在普通的编译器上绝对没有区别(除了第一个有更多的击键,第二个有不必要的括号(...)).在一些非常糟糕的优化编译器上,一种形式或另一种形式可能会更慢.

来自的真实结果x > y表示为,1而false表示为0.引用ISO/IEC 9899:201x委员会草案2011年4月12日N1570:

每个操作的<(小于), >(大于), <=(小于或等于),和>=(大于或等于)应得到1如果指定的关系为并且0如果它是假的.)结果有类型int.

而且a ? b : c是,如果表达式a的计算结果为真给人的值b,否则c.

因此,结果2是相同的.实际上,如果您编译此代码并反汇编它,您会注意到编译后的代码可能也不同:

int test1(int a, int b) {
    return a > b;
}

int test2(int a, int b){
    return a > b ? 1 : 0;
}
Run Code Online (Sandbox Code Playgroud)

在GCC 4.7.2,x86-64上编译,调试on(-g) - 这应该确保尽可能地禁用所有优化 - 然后反汇编objdump -d foo.o:

0000000000000000 <test1>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   89 7d fc                mov    %edi,-0x4(%rbp)
   7:   89 75 f8                mov    %esi,-0x8(%rbp)
   a:   8b 45 fc                mov    -0x4(%rbp),%eax
   d:   3b 45 f8                cmp    -0x8(%rbp),%eax
  10:   0f 9f c0                setg   %al
  13:   0f b6 c0                movzbl %al,%eax
  16:   5d                      pop    %rbp
  17:   c3                      retq   

0000000000000018 <test2>:
  18:   55                      push   %rbp
  19:   48 89 e5                mov    %rsp,%rbp
  1c:   89 7d fc                mov    %edi,-0x4(%rbp)
  1f:   89 75 f8                mov    %esi,-0x8(%rbp)
  22:   8b 45 fc                mov    -0x4(%rbp),%eax
  25:   3b 45 f8                cmp    -0x8(%rbp),%eax
  28:   0f 9f c0                setg   %al
  2b:   0f b6 c0                movzbl %al,%eax
  2e:   5d                      pop    %rbp
  2f:   c3                      retq   
Run Code Online (Sandbox Code Playgroud)

您可以看到2个函数的代码完全相同; 你不能推断哪一个编译到哪一个.表达式分为3行:

   d:   3b 45 f8                cmp    -0x8(%rbp),%eax
  10:   0f 9f c0                setg   %al
  13:   0f b6 c0                movzbl %al,%eax
Run Code Online (Sandbox Code Playgroud)

第一个比较b,以a和设置适当的处理器标志.al如果结果为"更大",则第二个设置(寄存器eax/rax的最低字节)为1(注意比较在上面反转!),否则为0; 第三个,movzbl将一个字节零扩展为32位整数,因为我们在int这里返回.