Thread: optimizations in if statements using true and false

  1. #1
    Counter-Strike Master
    Join Date
    Dec 2002
    Posts
    38

    Question optimizations in if statements using true and false

    my compiler is msvc++ 6.0. when using an if statement, which of these lines of code would run faster?

    Code:
    if(variable==0)
    or
    Code:
    if(!variable)
    also the same question with these 2 lines of code

    Code:
    if(variable==1)
    or
    Code:
    if(variable)
    i know that it probably wouldnt matter as far as optimizations go, but im just wondering from a technical standpoint.
    You say "Impressive!", but I already know it
    I'm a hardcore player and I'm not afraid to show it

  2. #2
    Registered User
    Join Date
    Apr 2004
    Posts
    210
    I don't have msvcc (or any windows box for that matter), but I'd assume any decent compiler will optimize both to the same assembler code. This is what GCC does:

    Code:
    #include <stdlib.h>
    extern volatile_exp;
      
    int test() {
      int x= rand();
      int y= rand();
    
      if (x == 0)
        volatile_exp= 10;
      
      if (!y)
        volatile_exp= 10;
    }
    Code:
    test:
      pushl %ebp
      movl  %esp, %ebp
      subl  $8, %esp
      movl  %ebx, -4(%ebp)
    
      # grab x,y, init with random value
      call  rand
      movl  %eax, %ebx
      call  rand
      # x now in ebx, y in eax
      
      # test x
      testl %ebx, %ebx
      jne .L20
      movl  $10, %ecx
      movl  %ecx, volatile_exp
    .L20:
    
      # test y
      testl %eax, %eax
      jne .L21
      movl  $10, %edx
      movl  %edx, volatile_exp
    .L21:
      
      movl  -4(%ebp), %ebx
      movl  %ebp, %esp
      popl  %ebp
      ret
    As you can see, it's exactly the same. Now, in completely unoptimized mode (if thats possible) that will probably look different. But I don't think performance matters if you turn off safe optimizations.
    Last edited by Nyda; 11-07-2004 at 05:41 AM. Reason: switched board-editor to finally get proper code :)
    main() { int O[!0<<~-!0]; (!0<<!0)[O]+= ~0 +~(!0|!0<<!0); printf("a function calling "); }

  3. #3
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    It's been suggested to me to use the short form for my own tests because it implies that I'm familar enough with the language to know the trick. This will impress people (especially interviewers) with my command of the language. My response has always been this: "I'm experienced enough to know the pitfalls of that construct and I choose not to use it because of them. I would rather have good code than make others think I'm some sort of C god." I'm telling that story because your question brings up an important issue about robust programming.

    >which of these lines of code would run faster?
    This isn't nearly as interesting as which of the lines would be more clear. In the end, the first two are identical in speed and even if they weren't, the difference would be infintesimally small. The second two are not the same because
    Code:
    if(variable==1)
    Tests variable to see if it's 1, and
    Code:
    if(variable)
    Tests variable to see if it's not 0. This mistake brings me back to the clarity issue. If you can't get the concise form right on the first try, then should you be using it in the first place? Would readers of your code be able to trust that you got it right?
    My best code is written with the delete key.

  4. #4
    Counter-Strike Master
    Join Date
    Dec 2002
    Posts
    38
    thanks for your help Nyda and Prelude. another one of programmings great mysteries answered
    You say "Impressive!", but I already know it
    I'm a hardcore player and I'm not afraid to show it

  5. #5
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >another one of programmings great mysteries answered
    What about: Why do hot dog buns come in packs of ten but hot dogs come in packs of eight? The answer of course is that hot dog manufacturers use the octal system and hot dog bun manufacturers use the decimal system. They both agreed that packs should hold ten items, but they forgot to agree on the numbering system.
    My best code is written with the delete key.

  6. #6
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    The two are slightly different, the first being true only when the expression == 1 and the second true for any value but 0. But, given a compiler that deduce-and-optimize your if-then chains, this difference in semantics shouldn't effect the resultant code if the expected result is the same, and if the difference is even worth it.

    Interestingly enough, distinction occurs with pointers, where many programmers, mostly C programmers, write "if (ptr == NULL)", while other programmers simply write "if (!ptr)". Well, they both have their reasons, NULL being defined somewhere in a file included by stdilb.h
    Last edited by okinrus; 11-07-2004 at 06:55 PM.

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    What distinction with pointers?
    http://www.eskimo.com/~scs/C-faq/q5.3.html
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  8. #8
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    Forgot to qualify distinction. What I meant here was that there is a stylistic distinction between C++ programmers and C programmers. In C, where practically every pointer use will use malloc somewhere, including stdlib.h is quite common. In C++, however, where pointers are commonly used with operator new, the use of "if (!p) or if (p != 0)" is quite common. In fact, the C++ faq, I believe to avoid #define's, recommends the use const void* null = 0 or something similar.

  9. #9
    The C-er
    Join Date
    Mar 2004
    Posts
    192
    Here's a variation on the theme:
    Code:
    #include <stdio.h>
    int main(void)
    {
    	int foo[100];
    	int bar[100];
    
    	for (int i=0;i<100;i++) foo[i]=i;
    	for (int i=100;i--;) bar[i]=i;
    	
    }
    The two loops have the same effect, however the second one compiles to tighter assembly on my system (LCC-win32) and runs faster.
    The arrays are just to illustrate a use for the loop indexing.

    I use this method for speed critical loops only, otherwise I stick to the idiomatic form.

  10. #10
    Registered User
    Join Date
    Jun 2004
    Posts
    722
    Quote Originally Posted by Jez
    Here's a variation on the theme:
    Code:
    #include <stdio.h>
    int main(void)
    {
    	int foo[100];
    	int bar[100];
    
    	for (int i=0;i<100;i++) foo[i]=i;
    	for (int i=100;i--;) bar[i]=i;
    	
    }
    The two loops have the same effect....
    Almost... the fact that i is incremented/decremented may be important in the cicle

    Quote Originally Posted by okinrus
    (...) NULL being defined somewhere in a file included by stdilb.h
    Defined in stdio.h

  11. #11
    The C-er
    Join Date
    Mar 2004
    Posts
    192
    Almost... the fact that i is incremented/decremented may be important in the cicle
    Yes one increments, one decrements, but they have the same effect (in this case)
    What's a cicle?

    Here's what I was playing with a few moments ago:

    Code:
    #include <stdio.h>
    #include <time.h>
    
    #define COUNT 1000000000
    #define TIMENOW (double)clock()/(double)CLOCKS_PER_SEC
    
    int main(void)
    {
    	for (int j=5;j--; )
    	{
    
    		int x=0;
    		double t1 = TIMENOW;
    		for (register int i=0;i<COUNT;i++) x++;
    		double t2 = TIMENOW;
    		printf ("time for idiomatic method = %f\t",t2-t1);
    		printf ("value of x = %d\n",x);
    
    		x=0;
    		t1 = TIMENOW;
    		for (register int i=COUNT;i--;) x++;
    		t2 = TIMENOW;
    		printf ("time for short method = %f\t",t2-t1);
    		printf ("value of x = %d\n",x);
    	}
    }
    I was just investigating why I got inconsistent results. The first version of this omitted the outer for loop (repeats 5 times), and just did the timings once. The short way was faster.
    Now it does it 5 times, and the idiomatic way is faster.

    I've looked at the assembly, and the short way looks better. It might be an optimization issue. I'll take another look at it tommorrow.

  12. #12
    Registered User
    Join Date
    Apr 2004
    Posts
    210
    Quote Originally Posted by Jez
    The two loops have the same effect, however the second one compiles to tighter assembly on my system (LCC-win32) and runs faster.
    The arrays are just to illustrate a use for the loop indexing.

    I use this method for speed critical loops only, otherwise I stick to the idiomatic form.
    Might well be true for your compiler, but in general I'd say it makes no difference at all. This is the incremental version, compiled with gcc -O3

    Code:
    	xorl	%eax, %eax
    .L6:
    	movl	%eax, foo(,%eax,4)
    	incl	%eax
    	cmpl	$99, %eax
    	jle	.L6
    and the other one:

    Code:
    	movl	$99, %eax
    .L11:
    	movl	%eax, bar(,%eax,4)
    	decl	%eax
    	cmpl	$-1, %eax
    	jne	.L11
    I'm not an expert in assembler programming, but I'm fairly certain the instructions within the loop (inc/decrement and conditional jumps) are executed at the same speed (that is, no additional overhead in the pipeline). Usually the initialization doesn't really matter, but since everything else is identical, I'd say that clearing a register with xor reg,reg is faster than filling it with an immediate. The effect is probably one of the closest things to "nothing".

    I'd really suggest to write readable code. Leave the optimization to the compiler. If neccessary, make a profiled compilation (if supported - if not get a better compiler). i.e. this let's the compiler detect slow loops and unroll them. Something you wouldn't want to do in your code anyways - unless you work for a company and want to make sure they can't fire you without losing all your work, that is
    main() { int O[!0<<~-!0]; (!0<<!0)[O]+= ~0 +~(!0|!0<<!0); printf("a function calling "); }

  13. #13
    </life>
    Join Date
    Oct 2004
    Posts
    83
    Why there is a light when open the fridge door, but not the freezer?

  14. #14
    Counter-Strike Master
    Join Date
    Dec 2002
    Posts
    38
    great question dagdarian. i hate having to hold the fridge door open with my foot so i can pick a tv dinner and set the microwave (which is one of those cheap 700 watt ones)
    You say "Impressive!", but I already know it
    I'm a hardcore player and I'm not afraid to show it

  15. #15
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >Why there is a light when open the fridge door, but not the freezer?
    The refrigerator gnomes don't live in the freezer because they don't have parkas. Duh.
    My best code is written with the delete key.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. BIG problem. How do I find a bug in so much code?
    By Yarin in forum C++ Programming
    Replies: 44
    Last Post: 01-31-2008, 12:39 PM
  2. C++ FTP class won't work
    By lord mazdak in forum C++ Programming
    Replies: 8
    Last Post: 12-18-2005, 07:57 AM
  3. Reducing Code size from ridiculous length
    By DanFraser in forum C# Programming
    Replies: 10
    Last Post: 01-18-2005, 05:50 PM
  4. Something is wrong with this menu...
    By DarkViper in forum Windows Programming
    Replies: 2
    Last Post: 12-14-2002, 11:06 PM