0

Possible Duplicate:
To “if, if, if” or to “if, else if, else if, else”

1.

if(flag == 1)
{
    .....
}
else if(flag == 2)
{ 
     .....
}
else if(flag == 3) // true condition
{
     .....
}

or
2.

if(flag == 1)
{
    .....
}
if(flag == 2)
{ 
     .....
}
if(flag == 3) // true condition
{
     .....
}

If its going to execute last if.

Community
  • 1
  • 1
Sachin Mhetre
  • 4,465
  • 10
  • 43
  • 68
  • 10
    They are generally not logically equivalent, and it depends on your compiler, how it optimizes things, and potentially on your platform. The only way to know is to benchmark with your specific data set. – Mat Apr 09 '12 at 10:32
  • I know that thay are not logically equivalent. But suppose same variable is used in each if statement for condtion. ie. if(flag == 1) else if(flag == 2) and so on. – Sachin Mhetre Apr 09 '12 at 10:35
  • I am not interested in switch statement. I am just asking this question for self improvments, so if this question is aksed in interview i shall be able to answer it – Sachin Mhetre Apr 09 '12 at 10:37
  • Read the rest of my comment: it depends. You need to benchmark on your platform with your expected data. – Mat Apr 09 '12 at 10:37
  • This is a decent Qn but might be a duplicate. Why downvotes? – Pavan Manjunath Apr 09 '12 at 10:58

6 Answers6

6

My test shows that 2nd version is 4 instructions shorter than previous one but optimized version is the same long:

I test
Code:

main(a) {
  if(a == 10)
    puts("10");
  else if(a == 20)
    puts("20");
  else if(a < 100)
    puts("yes");
}

Disassm:

   0x00000000004004dc <+0>: push   rbp
   0x00000000004004dd <+1>: mov    rbp,rsp
   0x00000000004004e0 <+4>: sub    rsp,0x10
   0x00000000004004e4 <+8>: mov    DWORD PTR [rbp-0x4],edi
   0x00000000004004e7 <+11>:    cmp    DWORD PTR [rbp-0x4],0xa
   0x00000000004004eb <+15>:    jne    0x4004f9 <main+29>
   0x00000000004004ed <+17>:    mov    edi,0x4005c4
   0x00000000004004f2 <+22>:    call   0x4003b0 <puts@plt>
   0x00000000004004f7 <+27>:    jmp    0x40051b <main+63>
   0x00000000004004f9 <+29>:    cmp    DWORD PTR [rbp-0x4],0x14
   0x00000000004004fd <+33>:    jne    0x40050b <main+47>
   0x00000000004004ff <+35>:    mov    edi,0x4005c7
   0x0000000000400504 <+40>:    call   0x4003b0 <puts@plt>
   0x0000000000400509 <+45>:    jmp    0x40051b <main+63>
   0x000000000040050b <+47>:    cmp    DWORD PTR [rbp-0x4],0x63
   0x000000000040050f <+51>:    jg     0x40051b <main+63>
   0x0000000000400511 <+53>:    mov    edi,0x4005ca
   0x0000000000400516 <+58>:    call   0x4003b0 <puts@plt>
   0x000000000040051b <+63>:    leave  
   0x000000000040051c <+64>:    ret    

Optimized:

   0x00000000004004dc <+0>: sub    rsp,0x8
   0x00000000004004e0 <+4>: cmp    edi,0xa
   0x00000000004004e3 <+7>: jne    0x4004f1 <main+21>
   0x00000000004004e5 <+9>: mov    edi,0x4005c4
   0x00000000004004ea <+14>:    call   0x4003b0 <puts@plt>
   0x00000000004004ef <+19>:    jmp    0x400511 <main+53>
   0x00000000004004f1 <+21>:    cmp    edi,0x14
   0x00000000004004f4 <+24>:    jne    0x400502 <main+38>
   0x00000000004004f6 <+26>:    mov    edi,0x4005c7
   0x00000000004004fb <+31>:    call   0x4003b0 <puts@plt>
   0x0000000000400500 <+36>:    jmp    0x400511 <main+53>
   0x0000000000400502 <+38>:    cmp    edi,0x63
   0x0000000000400505 <+41>:    jg     0x400511 <main+53>
   0x0000000000400507 <+43>:    mov    edi,0x4005ca
   0x000000000040050c <+48>:    call   0x4003b0 <puts@plt>
   0x0000000000400511 <+53>:    add    rsp,0x8
   0x0000000000400515 <+57>:    ret   

II test
Code:

main(a) {
  if(a == 10)
    puts("10");
  if(a == 20)
    puts("20");
  if(a < 100)
    puts("yes");
}

Disassm:

   0x00000000004004dc <+0>: push   rbp
   0x00000000004004dd <+1>: mov    rbp,rsp
   0x00000000004004e0 <+4>: sub    rsp,0x10
   0x00000000004004e4 <+8>: mov    DWORD PTR [rbp-0x4],edi
   0x00000000004004e7 <+11>:    cmp    DWORD PTR [rbp-0x4],0xa
   0x00000000004004eb <+15>:    jne    0x4004f7 <main+27>
   0x00000000004004ed <+17>:    mov    edi,0x4005c4
   0x00000000004004f2 <+22>:    call   0x4003b0 <puts@plt>
   0x00000000004004f7 <+27>:    cmp    DWORD PTR [rbp-0x4],0x14
   0x00000000004004fb <+31>:    jne    0x400507 <main+43>
   0x00000000004004fd <+33>:    mov    edi,0x4005c7
   0x0000000000400502 <+38>:    call   0x4003b0 <puts@plt>
   0x0000000000400507 <+43>:    cmp    DWORD PTR [rbp-0x4],0x63
   0x000000000040050b <+47>:    jg     0x400517 <main+59>
   0x000000000040050d <+49>:    mov    edi,0x4005ca
   0x0000000000400512 <+54>:    call   0x4003b0 <puts@plt>
   0x0000000000400517 <+59>:    leave  
   0x0000000000400518 <+60>:    ret

Optimized:

   0x00000000004004dc <+0>: sub    rsp,0x8
   0x00000000004004e0 <+4>: cmp    edi,0xa
   0x00000000004004e3 <+7>: jne    0x4004f1 <main+21>
   0x00000000004004e5 <+9>: mov    edi,0x4005c4
   0x00000000004004ea <+14>:    call   0x4003b0 <puts@plt>
   0x00000000004004ef <+19>:    jmp    0x400507 <main+43>
   0x00000000004004f1 <+21>:    cmp    edi,0x14
   0x00000000004004f4 <+24>:    jne    0x400502 <main+38>
   0x00000000004004f6 <+26>:    mov    edi,0x4005c7
   0x00000000004004fb <+31>:    call   0x4003b0 <puts@plt>
   0x0000000000400500 <+36>:    jmp    0x400507 <main+43>
   0x0000000000400502 <+38>:    cmp    edi,0x63
   0x0000000000400505 <+41>:    jg     0x400511 <main+53>
   0x0000000000400507 <+43>:    mov    edi,0x4005ca
   0x000000000040050c <+48>:    call   0x4003b0 <puts@plt>
   0x0000000000400511 <+53>:    add    rsp,0x8
   0x0000000000400515 <+57>:    ret 

Booth test are compiled by gcc version 4.7.0 20120324 (prerelease) (GCC) on Linux 3.2.14-1-ARCH x86_64 Intel(R) Core(TM) i5 CPU M 480 @ 2.67GHz.

EDIT: as @Als suggested I will give version with basic optimisations (-O flag in GCC).

Hauleth
  • 22,873
  • 4
  • 61
  • 112
  • 1
    Since the Q is specifically about performance,It would make sense to run the tests by enabling the optimizations.You might end up with the same assembly instructions if you enable the optimizations. – Alok Save Apr 09 '12 at 10:49
  • I can try, but it will be a long post then. Questioner can do it by himself. When you will have 5 or more votes up then I do it :) – Hauleth Apr 09 '12 at 10:51
  • In that case, this is a misleading answer, which gets my -1. – Alok Save Apr 09 '12 at 10:52
  • Note that with optimization on, I see no such difference (the assembly is the same, except some `ret`s ar replaced for `jmp`, since the second version is not equivalent to the first. – jpalecek Apr 09 '12 at 11:00
  • 1
    Removed the downvote.As expected with optimizations enabled there is no difference.And hopefully, that justify's my comment on answer being misleading initially. – Alok Save Apr 09 '12 at 11:16
5

They are not logically equivalent.
First will not check for other if conditions once it finds a matching condition.
Second checks every if condition regardless of any previous matching.

If you are using return statements inside the if blocks in second case then, they would be logically equivalent.And I believe equally performant.
However, You will need to profile them on your environment to be sure.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
3

Technically, the two code snippets you have provided are not equivalent, and so it does not make sense to compare them.

It is possible that more than one if block will execute in the second sample, while the first guarantees only one path of executive through the block. So on this point, it may be said that the first would execute quicker if you suppose that on average more than one condition will succeed.

However, if you make the assumption that only one path will ever execute, it is no longer possible to say with any certainty unless you have knowledge of how your compiler will translate this code into assembly, because assembly does not have a conditional primitive (ie if-else).

Assembly language uses instructions such as Compare, Jump if less than zero and Jump if zero to implement conditional logic. Without being aware of the relevant optimizations the compiler may make it is impossible to say which would execute faster.

ose
  • 4,065
  • 2
  • 24
  • 40
0

Same time; If the first if condition is true, then the first block of the code will execute fast.

Anthony
  • 12,177
  • 9
  • 69
  • 105
Nagaraju Badaeni
  • 890
  • 8
  • 14
0

Logically, the code snippets are not equivalent isn't it. For instance, the first one says

if (a==0)
{
}
else if (a < 10)
{
}
else if (a > 10)
{
}

The second one is

if (a ==0)
{
}
if (a < 10)
{
}
if (a > 10)
{
}

The above is a very trivial illustration. But, if you are trying to compare the time of execution of the if-statements, assuming they are logically equivalent, then the first one will be faster since the else statements will never be executed. In the second case, the if conditions will be evaluated irrespective of the earlier if statements.

Gangadhar
  • 1,893
  • 9
  • 9
0

Just to add to @Haulet's post, this is what I got when compiling with optimization:

jirka@debian:~/xpath/libxml-xpathengine-perl$ diff -Naur ./-.s o2.s 
--- ./-.s       2012-04-09 12:50:50.000000000 +0200
+++ o2.s        2012-04-09 12:52:25.000000000 +0200
@@ -22,43 +22,34 @@
        subl    $16, %esp
        movl    8(%ebp), %eax
        cmpl    $10, %eax
-       je      .L8
-       cmpl    $20, %eax
        je      .L9
+       cmpl    $20, %eax
+       je      .L10
        cmpl    $99, %eax
-       jle     .L10
+       jle     .L3
        leave
        .cfi_remember_state
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        .p2align 4,,4
        ret
-.L10:
-       .cfi_restore_state
-       movl    $.LC2, (%esp)
-       call    puts
-       leave
-       .cfi_remember_state
-       .cfi_restore 5
-       .cfi_def_cfa 4, 4
-       ret
-.L8:
+.L9:
        .cfi_restore_state
        movl    $.LC0, (%esp)
        call    puts
+.L3:
+       movl    $.LC2, (%esp)
+       call    puts
        leave
        .cfi_remember_state
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret
-.L9:
+.L10:
        .cfi_restore_state
        movl    $.LC1, (%esp)
        call    puts
-       leave
-       .cfi_restore 5
-       .cfi_def_cfa 4, 4
-       ret
+       jmp     .L3
        .cfi_endproc
 .LFE0:
        .size   main, .-main

As you can see, the labels have been relabeled (L8 -> L9, L9 -> L10, L10 -> L3), but the code is by and large the same (except as needed for functional differences).

I compiled with

gcc-4.7 -S -O3 -march=k8 -x c - 
jpalecek
  • 47,058
  • 7
  • 102
  • 144