如果(标志 = = 0)或者如果(0 = = 标志) ,哪一个会执行得更快?

面试问题: if (flag==0)if (0==flag)哪个执行速度更快? 为什么?

26194 次浏览

在速度上绝对不会有差别,为什么会有差别呢?

当然,在执行速度方面没有差别。在这两种情况下,条件都需要以相同的方式进行评估。

There is absolutely no difference.

不过,在回答这个面试问题时,你可以参考排除作业/比较拼写错误的方法,从而获得积分:

if (flag = 0)  // typo here
{
// code never executes
}


if (0 = flag) // typo and syntactic error -> compiler complains
{
// ...
}

虽然这是事实,例如,C 编译器确实警告前者(flag = 0) ,但在 PHP、 Perl 或 Javascript 或 <insert language here>中没有这样的警告。

They should be exactly the same in terms of speed.

然而请注意,有些人在等式比较中使用左边的常量(所谓的“ Yoda 条件句”)来避免所有可能出现的错误,如果你写 =(赋值运算符)而不是 ==(等式比较运算符) ; 因为赋值给一个文字会触发一个编译错误,所以这种错误是可以避免的。

if(flag=0) // <--- typo: = instead of ==; flag is now set to 0
{
// this is never executed
}


if(0=flag) // <--- compiler error, cannot assign value to literal
{


}

另一方面,大多数人觉得“ Yoda 条件句”看起来很奇怪,很烦人,特别是因为它们可以通过使用适当的编译器警告来发现它们所防止的错误类。

if(flag=0) // <--- warning: assignment in conditional expression
{


}

你们的版本不会有任何区别。

我假设标志的 type不是用户定义的类型,而是某种内置类型。Enum 是例外!.您可以将 enum 视为内置的。事实上,它的值是内置类型之一!

在这种情况下,如果它是用户定义的类型(除了 enum) ,那么答案完全取决于您如何重载操作符 ==。注意,您必须通过定义两个函数来重载 ==,每个函数对应于您的版本!

正如其他人所说,没有区别。

必须对 0进行评估。必须对 flag进行评估。这个过程需要相同的时间,不管它们放在哪一边。

The right answer would be: they're both the same speed.

甚至表达式 if(flag==0)if(0==flag)都有相同数量的字符!如果其中一个被写成 if(flag== 0),那么编译器将有一个额外的空间来解析,因此您将有一个合理的理由来指出编译时间。

但是既然没有这样的东西,那么就绝对没有理由让一个人比另一个人快。如果有原因的话,那么编译器正在对生成的代码做一些非常非常奇怪的事情..。

好吧,为了练习起见,我完全同意在对《任择议定书》的评论中所说的一切:

如果编译器不够聪明(实际上您不应该使用它)或者禁用了优化,x == 0可以编译成一个本机汇编 jump if zero指令,而 0 == x可以是一个更通用(和昂贵)的数值比较。

尽管如此,我还是不愿意为一个用这些术语思考的老板工作。

使用建议的方法构建两个简单的程序。

组装密码。看看这个组装,你就能判断了,但是我怀疑有什么不同!

面试越来越少了。

我还没有看到任何正确的答案(已经有一些) 警告: 纳瓦兹确实指出了用户定义的陷阱。我对自己仓促投票选择“最愚蠢的问题”感到遗憾,因为似乎很多人都没有选对,这给了我们一个很好的编译器最佳化讨论空间:)

答案是:

flag的类型是什么?

flag实际上是用户定义类型的情况下。然后取决于选择哪个 operator==重载。当然,它们不是对称的,这看起来很愚蠢,但这当然是允许的,我已经看到了其他的滥用。

如果 flag是内置的,那么两者应该采取相同的速度。

x86上的 Wikipedia article,我打赌 Jxx指令用于 if语句: 可能是 JNZ(如果不为零则跳转)或其他等价物。

我怀疑编译器错过了如此明显的优化,即使关闭了优化。窥视孔优化就是为这种类型的事情而设计的。

EDIT: Sprang up again, so let's add some assembly (LLVM 2.7 IR)

int regular(int c) {
if (c == 0) { return 0; }
return 1;
}


int yoda(int c) {
if (0 == c) { return 0; }
return 1;
}


define i32 @regular(i32 %c) nounwind readnone {
entry:
%not. = icmp ne i32 %c, 0                       ; <i1> [#uses=1]
%.0 = zext i1 %not. to i32                      ; <i32> [#uses=1]
ret i32 %.0
}


define i32 @yoda(i32 %c) nounwind readnone {
entry:
%not. = icmp ne i32 %c, 0                       ; <i1> [#uses=1]
%.0 = zext i1 %not. to i32                      ; <i32> [#uses=1]
ret i32 %.0
}

Even if one does not know how to read the IR, I think it is self explanatory.

与 GCC 4.1.2中的 amd64相同的代码:

        .loc 1 4 0  # int f = argc;
movl    -20(%rbp), %eax
movl    %eax, -4(%rbp)
.loc 1 6 0 # if( f == 0 ) {
cmpl    $0, -4(%rbp)
jne     .L2
.loc 1 7 0 # return 0;
movl    $0, -36(%rbp)
jmp     .L4
.loc 1 8 0 # }
.L2:
.loc 1 10 0 # if( 0 == f ) {
cmpl    $0, -4(%rbp)
jne     .L5
.loc 1 11 0 # return 1;
movl    $1, -36(%rbp)
jmp     .L4
.loc 1 12 0 # }
.L5:
.loc 1 14 0 # return 2;
movl    $2, -36(%rbp)
.L4:
movl    -36(%rbp), %eax
.loc 1 15 0 # }
leave
ret

当有疑问的基准,并了解真相。

当标志是用户定义的类型时,这是有区别的

struct sInt
{
sInt( int i ) : wrappedInt(i)
{
std::cout << "ctor called" << std::endl;
}


operator int()
{
std::cout << "operator int()" << std::endl;
return wrappedInt;
}


bool operator==(int nComp)
{
std::cout << "bool operator==(int nComp)" << std::endl;
return (nComp == wrappedInt);
}


int wrappedInt;
};


int
_tmain(int argc, _TCHAR* argv[])
{
sInt s(0);


//in this case this will probably be faster
if ( 0 == s )
{
std::cout << "equal" << std::endl;
}


if ( s == 0 )
{
std::cout << "equal" << std::endl;
}
}

在第一种情况下(0 = = s)调用转换运算符,然后将返回的结果与0进行比较。在第二种情况下,调用 = = 运算符。

我认为最好的答案是“这个例子是用什么语言写的”?

这个问题没有指定语言,而且标记了“ C”和“ C + +”。一个精确的答案需要更多的信息。

这是一个糟糕的编程问题,但是在狡猾的“让我们给被采访者足够的绳子,要么上吊自杀,要么建一个树秋千”部门,这可能是一个好问题。这类问题的问题在于,它们通常会被记录下来,从面试官传到面试官那里,直到传到那些从各个角度都不能真正理解它们的人那里。

Which one's fast depends on which version of == you are using. Here's a snippet that uses 2 possible implementations of ==, and depending on whether you choose to call x == 0 or 0 == x one of the 2 is selected.

如果你只是使用一个 POD 这真的不应该有关系,当涉及到速度。

#include <iostream>
using namespace std;


class x {
public:
bool operator==(int x) { cout << "hello\n"; return 0; }
friend bool operator==(int x, const x& a) { cout << "world\n"; return 0; }
};


int main()
{
x x1;
//int m = 0;
int k = (x1 == 0);
int j = (0 == x1);
}

正如一个旁白(我实际上认为任何一个像样的编译器都会让这个问题变得毫无意义,因为它会优化它)使用0 = = 标志优于标志 = = 0可以防止你忘记了一个 = (即如果你不小心输入了 Flag = 0它会编译,但是0 = 标志不会) ,我认为这是每个人在某个时候都会犯的错误。

If at all there was a difference, what stops compiler to choose the faster once? So logically, there can't be any difference. Probably this is what the interviewer expects. It is actually a brilliant question.