113

Interview question: Which one will execute faster, if (flag==0) or if (0==flag)? Why?

MD XF
  • 7,860
  • 7
  • 40
  • 71
Vishwanath Dalvi
  • 35,388
  • 41
  • 123
  • 155
  • 331
    Nominated for the stupidest interview question ever. And there’s a stiff competition. – Konrad Rudolph Jan 07 '11 at 10:26
  • 120
    You: Name a situation where the difference between these two could possibly be worth bothering with. Interviewer: Okay, you're hired. – Chris Lutz Jan 07 '11 at 10:27
  • 8
    I hope the company isn't actually using a compiler that generates the binary in such a way that the code actually makes a difference in performance. – In silico Jan 07 '11 at 10:28
  • 37
    The only difference between the two is that with the later convention, you're insured against bugs like `if(flag = 0)` at the price of a little readability. – Amarghosh Jan 07 '11 at 10:28
  • 6
    People might have genuine doubts. Let them ask it. Why people here think people are born-knowledgeable or born-programmer? – Nawaz Jan 07 '11 at 10:48
  • 22
    @Amarghosh: At the cost of making your code hard to read and unintuitive. Use the former at turn on your compiler warnings, win-win. – GManNickG Jan 07 '11 at 11:21
  • 6
    @Amarghosh: no, you're protected against a *small subset* of this type of errors. Your code will explode just as badly if you replace `0` with an `expectedValue` variable. – jalf Jan 07 '11 at 11:57
  • 3
    The real question is, who writes `if (0==flag)`? I am terrified that the answer to this question could reveal that generations of coders have wasted quattuordecillions of CPU cycles because we think logically instead of optimally. – Jamie Treworgy Jan 07 '11 at 14:33
  • 12
    premature optimization vs optimization premature – Hernán Eche Jan 07 '11 at 16:06
  • 130
    Once a compiler writer got this in his interview. He whispered in response, "which one do _you_ want to be faster?". –  Jan 07 '11 at 17:21
  • 3
    @jamietre: this form has another benefit, it's been advocated by people who were afraid of accidentally writing `if (flag = 0)` thus overwriting flag and testing it in one go. gcc (at least) warns about it: "warning: suggest parentheses around assignment used as truth value" – Matthieu M. Jan 07 '11 at 17:39
  • 3
    The historical perspective is completely lost on this question. Am I the only one that ever used a crappy C compiler in the previous century? I'm getting old, it seems. No. – Hans Passant Jan 07 '11 at 22:28
  • 2
    @Hans You are not alone. I'm trying to break this habit having moved on from C/C++. @Amarghosh I got so used to `literal == variable` that I found the other way around less readable :-) – Richard Jan 08 '11 at 13:29
  • 6
    Is this why C++ developers can't get real work done?:) – JR Kincaid Jan 10 '11 at 19:16
  • I don't think it's a bad question at all. I guess the interviewer expects the candidate talks about premature optimization. – Yann Trevin Jan 21 '11 at 09:34
  • this is just a trap, to make the developer explain that it is better to avoid comoon C mistakes – Mandrake Jan 29 '11 at 12:41
  • I am guessing the answer they were looking for is that "they are the same but 0==flag is safer, as if you forgot an = it will result in a complile time error, instead of assigning 0 to flag." – Myforwik May 22 '14 at 00:33

16 Answers16

238

I haven't seen any correct answer yet (and there are already some) caveat: Nawaz did point out the user-defined trap. And I regret my hastily cast upvote on "stupidest question" because it seems that many did not get it right and it gives room for a nice discussion on compiler optimization :)

The answer is:

What is flag's type?

In the case where flag actually is a user-defined type. Then it depends on which overload of operator== is selected. Of course it can seem stupid that they would not be symmetric, but it's certainly allowed, and I have seen other abuses already.

If flag is a built-in, then both should take the same speed.

From the Wikipedia article on x86, I'd bet for a Jxx instruction for the if statement: perhaps a JNZ (Jump if Not Zero) or some equivalent.

I'd doubt the compiler misses such an obvious optimization, even with optimizations turned off. This is the type of things for which Peephole Optimization is designed for.

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.

user703016
  • 37,307
  • 8
  • 87
  • 112
Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • 4
    @Matthieu : you said *I haven't seen any correct answer yet*.. but mine is correct, i think :P – Nawaz Jan 07 '11 at 11:28
  • 7
    good! your answer possible turns "the stupidest question" to "the trickies/meanest". "let's dig a hole for the candidate and see if he falls into it..." :) I guess we all automatically assume that `flag` must be integer or boolean. OTOH, having a variable named `flag` of a user-defined type is quite wrong on itself, IMHO – davka Jan 07 '11 at 11:50
  • @Nawaz: I may have skipped the last paragraph of your answer :p – Matthieu M. Jan 07 '11 at 13:16
  • @Matthieu : And I know the reason. It's all because of the race for upvotes :P – Nawaz Jan 07 '11 at 13:18
  • 1
    @Nawaz: I don't really race, I usually read questions long after they've been answered and people tend to read only the first most upvoted answers :) But I am actually reading stuff on compiler optimizations, and this struck me as a typical case of trivial optimization so I thought I would point it out for those readers who actually bother... I am pretty surprised actually I got so many upvotes. Now it's my most voted answer even though it's certainly not the one in which I put the most effort :/ Anyway I edited my answer and corrected my statement :) – Matthieu M. Jan 07 '11 at 13:28
  • 2
    @mr_eclair: a built-in type is a type that is (as the name implied) built-in in the language. That is, it is available even without a single `#include` directive. For simplicity's sake, it usually amounts to `int`, `char`, `bool` and the like. All the other types are said to be user-defined, that is they exist because they are the result of some user declaring them: `typedef`, `enum`, `struct`, `class`. For example, `std::string` is user defined, even though you certainly not defined it yourself :) – Matthieu M. Jan 07 '11 at 14:29
  • @Spudley: I must admit I am kind of impressed too oO Even though it's useless (reputations and badges don't really achieve anything :p) and I am not really sure I deserved it for such a short answer, I still feel flattered. – Matthieu M. Jan 08 '11 at 15:49
56

There will be no difference in your versions.

I'm assuming that the type of flag is not user-defined type, rather it's some built-in type. Enum is exception!. You can treat enum as if it's built-in. In fact, it' values are one of built-in types!

In case, if it's user-defined type (except enum), then the answer entirely depends on how you've overloaded the operator == . Note that you've to overload == by defining two functions, one for each of your versions!

Shahbaz
  • 46,337
  • 19
  • 116
  • 182
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 8
    this could be the only possible reason to ask this question, IMHO – davka Jan 07 '11 at 10:33
  • 15
    I would be extremely surprised if modern compilers missed such an obvious optimization. – Pedro d'Aquino Jan 07 '11 at 10:36
  • 1
    The use of bitwise operations is irrelevant; the (incredibly retarded interview) question was whether `if(flag==0)` or `if(0==flag)` was faster. – In silico Jan 07 '11 at 10:37
  • Why would it be faster? I 'd be very interested to learn about this if it's true. – Jon Jan 07 '11 at 10:38
  • possibly dependent on what `flag` is, but still, +1 – darioo Jan 07 '11 at 10:40
  • 3
    To my knowledge ! is not a bitwise operation – Xavier Combelle Jan 07 '11 at 10:53
  • 1
    @darioo: definitely dependent, for user-defined type you just cannot assume anything. – Matthieu M. Jan 07 '11 at 11:04
  • 1
    @Xavier : You're right. I actually meant logical operator. I corrected my post. Thanks for pointing out it. :-) – Nawaz Jan 07 '11 at 11:18
  • 8
    @Nawaz: didn’t downvote but your answer is factually wrong and it’s horrible that it still got so many upvotes. For the record, comparing an integer to 0 is **a single assembly instruction**, completely on par with negation. In fact, if the compiler is slightly stupid then this could even be **faster** than negation (not likely though). – Konrad Rudolph Jan 07 '11 at 12:32
  • @Konrad : I just checked it out. The assembly generated is exactly same for both. I used MinGW's gcc! – Nawaz Jan 07 '11 at 12:42
  • 6
    @Nawaz: it's still wrong to say that it can, will, or usually will, be faster. *If* there is a difference, then the "compare against zero" version will be faster, since the negation one really translates into two operations: "negate operand; check that result is nonzero". In practice, of course, the compiler optimizes it to yield the same code as the plain "compare with zero" version, but the optimization is being applied to the negation version, to make it catch up, and not the other way around. Konrad is right. – jalf Jan 07 '11 at 13:32
  • @jalf : I agree with you. I realise that now. :-) – Nawaz Jan 07 '11 at 13:37
  • @Nawaz: "Enum is exception!" - no it's not... you can indeed create `operator==(Some_Enum, int)` or `...(int, Some_Enum)`. And it's just as relevant whether the user-defined type can only be compared after a conversion operator rather than with an `operator==`. – Tony Delroy Apr 08 '11 at 17:31
56

Same code for amd64 with GCC 4.1.2:

        .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
skc
  • 561
  • 3
  • 2
27

There is absolutely no difference.

You might gain points in answering that interview question by referring to the elimination of assignment/comparison typos, though:

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

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

While it's true, that e.g. a C-compiler does warn in case of the former (flag = 0), there are no such warnings in PHP, Perl or Javascript or <insert language here>.

Linus Kleen
  • 33,871
  • 11
  • 91
  • 99
  • @Matthieu Huh. I must have missed the post on *meta* describing the "proper" bracing style. – Linus Kleen Jan 07 '11 at 10:52
  • Well, both typos won't compile. – Magnus Jan 07 '11 at 11:40
  • 7
    I haven't voted at all, but for what it's worth: why is it so important that people explain themselves whenever they cast a vote? The votes are anonymous by design. I'm entirely opposed the idea that downvoters should always comment, because I personally don't ever want to be assumed to be the downvoter just because I left a comment pointing out a problem. Perhaps the downvoter thought the majority of the answer was irrelevant to the speed question? Perhaps he thought it encouraged a coding style he didn't approve of? Perhaps he was a dick, and wanted his own answer to have the highest rating? – David Hedlund Jan 07 '11 at 12:15
  • 3
    People should be free to vote as they will, regardless of the reason. Reputation-wise, this is almost always a good thing as it often provokes other people to upvote, to counter for the undeserved downvote, when in fact, a single upvote would cancel out five undeserved downvotes. – David Hedlund Jan 07 '11 at 12:16
  • @David While I'm way beyond the point of crying over -2 rep, as suggested, when clicking to down vote, I leave a comment. There has got to be a reason for a dislike. Commenting on that is also a way to improve future answers. If it's bracing, for example, the downvoter *might* point to a post on *meta* where proper bracing is addressed. Just my two cents. – Linus Kleen Jan 07 '11 at 12:37
  • 26
    @David: Downvoters should explain themselves because this site is not about secret popularity ballots, anonymous voting, or the like. This site is about learning. If someone says that a response is incorrect by downvoting it, the the downvoter is being selfish with their knowledge if they dont explain why. They are willing to take all the credit for when they are right, but not willing to share knowledge when others are wrong. – John Dibling Jan 07 '11 at 13:06
  • 1
    Just to get the bracing style issue out of the way, I really really think Matthieu intended that as a joke. I'd be surprised to see that anybody casts their votes depending on such issues. Having said that, not everybody uses the votes in exactly the same manner. I could see the rationale for downvoting because the post seems to advocate a coding style that the voter might disapprove of (note the difference between *advocating* a coding style - "if you write your code like this, you'll get compiler error when you make this typo" - and simply *using* a coding style, such as braces) In that... – David Hedlund Jan 07 '11 at 13:30
  • ...case, the voter might simply want to influence what style gains greater prominence, without necessarily making the argument that one style is *wrong*. I'm not saying I'm doing this, I'm just saying I can see a case for it. My only personal interest in all this is, as stated, that I don't want to be assumed the downvoter just because I remark on something negative. – David Hedlund Jan 07 '11 at 13:31
  • @goreSplatter: there is none, don't worry, but Whitesmiths is uncommon... anyway it's been a plague for a while that some posts are downvoted for no obvious reasons. @John: Wow, could not have said it better! – Matthieu M. Jan 07 '11 at 13:32
  • God, I'm glad we're past the bracing now. @Matthieu I like your answer, btw. – Linus Kleen Jan 07 '11 at 13:34
  • I suspect the downvote was from someone who didn't really read the answer properly; they just saw the single-equals, stopped reading there, and assumed the answer was being stupid. Its actually quite an easy mistake to make; if there's one thing this site does encourage, its speed-reading - with the rate at which answers get posted, if you don't read and write quickly, its easy to miss out on giving an answer. [oh, and for the record, the downvote wasn't me either!] – Spudley Jan 07 '11 at 14:04
16

There will be absolutely no difference speed-wise. Why should there be?

Jon
  • 428,835
  • 81
  • 738
  • 806
  • 7
    if the compiler was completely retarded. That's the only reason. – JeremyP Jan 07 '11 at 11:00
  • @JeremyP: I can't imagine a difference even if the compiler were retarded. The compiler writer would have to do it *on purpose* as far as I can tell. – Jon Jan 07 '11 at 11:02
  • 2
    Assuming the processor has a "test if 0" instruction, `x == 0` might use it but `0 == x` might use a normal compare. I did say it would have to be retarded. – JeremyP Jan 07 '11 at 11:08
  • 8
    If flag is a user-defined type with an asymmetric overload of operator==() – OrangeDog Jan 07 '11 at 16:16
  • Because we *might* have `virtual operator==(int)` in a user-defined type? – lorro Jul 28 '16 at 11:34
12

Well there is a difference when flag is a user defined type

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;
    }
}

In the first case (0==s) the conversion operator is called and then the returned result is compared to 0. In the second case the == operator is called.

ds27680
  • 1,993
  • 10
  • 11
11

When in doubt benchmark it and learn the truth.

Elzo Valugi
  • 27,240
  • 15
  • 95
  • 114
  • 2
    whats wrong with benchmarking? sometimes the practice is telling you more than the theory – Elzo Valugi Jan 07 '11 at 12:35
  • 1
    That's the answer I was looking for when I started reading this thread. It seems that theory is more appealing than practice, looking the answers and upvotes :) – Samuel Rivas Jan 20 '11 at 22:47
  • how could he benchmark at interview? plus i think the interviewer doesn't even know what benchmarking means, so he could have gotten offended. – IAdapter Jan 21 '11 at 21:07
  • They right answer to the question (IMO) is "That pretty much depends on the compiler and the rest of the program. I'd write a benchmark and test it in 5 minutes" – Samuel Rivas Feb 06 '11 at 10:02
7

They should be exactly the same in terms of speed.

Notice however that some people use to put the constant on the left in equality comparisons (the so-called "Yoda conditionals") to avoid all the errors that may arise if you write = (assignment operator) instead of == (equality comparison operator); since assigning to a literal triggers a compilation error, this kind of mistake is avoided.

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
{

}

On the other hand, most people find "Yoda conditionals" weird-looking and annoying, especially since the class of errors they prevent can be spotted also by using adequate compiler warnings.

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

}
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
5

As others have said, there is no difference.

0 has to be evaluated. flag has to be evaluated. This process takes the same time, no matter which side they're placed.

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

Even the expressions if(flag==0) and if(0==flag) have the same amount of characters! If one of them was written as if(flag== 0), then the compiler would have one extra space to parse, so you would have a legitimate reason at pointing out compile time.

But since there is no such thing, there is absolutely no reason why one should be faster than other. If there is a reason, then the compiler is doing some very, very strange things to generated code...

darioo
  • 46,442
  • 10
  • 75
  • 103
5

Well, I am agreeing completely with all said in the comments to the OP, for the exercise sake:

If the compiler is not clever enough (indeed you should not use it) or the optimization is disabled, x == 0 could compile to a native assembly jump if zero instruction, while 0 == x could be a more generic (and costly) comparison of numeric values.

Still, I wouldn't like to work for a boss who thinks in these terms...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
davka
  • 13,974
  • 11
  • 61
  • 86
5

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.

If you are just using a POD this really shouldn't matter when it comes to speed.

#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);
}
Fanatic23
  • 3,378
  • 2
  • 28
  • 51
4

Surely no difference in terms of execution speeds. The condition needs to be evaluated in both cases in the same way.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sachin Shanbhag
  • 54,530
  • 11
  • 89
  • 103
3

Build two simple programs using the suggested ways.

Assemble the codes. Look at the assembly and you can judge, but I doubt there is a difference!

Interviews are getting lower than ever.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Syntax_Error
  • 5,964
  • 15
  • 53
  • 73
3

I think the best answer is "what language is this example in"?

The question did not specify the language and it's tagged both 'C' and 'C++'. A precise answer needs more information.

It's a lousy programming question, but it could be a good in the devious "let's give the interviewee enough rope to either hang himself or build a tree swing" department. The problem with those kinds of questions is they usually get written down and handed down from interviewer to interviewer until it gets to people who don't really understand it from all the angles.

Marsh Ray
  • 2,827
  • 21
  • 20
2

Just as an aside ( I actually think any decent compiler will make this question moot, since it will optimise it ) using 0 == flag over flag == 0 does prevent the typo where you forget one of the = ( ie if you accidently type flag = 0 it will compile, but 0 = flag will not ), which I think is a mistake everyone has made at one point or another...

Kindread
  • 926
  • 4
  • 12
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.

balki
  • 26,394
  • 30
  • 105
  • 151