I was just thinking is there any performance difference between the 2 statements in C/C++:
Case 1:
if (p==0) do_this(); else if (p==1) do_that(); else if (p==2) do_these():
Case 2:
if(p==0) do_this(); if(p==1) do_that(); if(p==2) do_these();
In general, "else if" style can be faster because in the series of ifs, every condition is checked one after the other; in an "else if" chain, once one condition is matched, the rest are bypassed.
Use if to specify a block of code to be executed, if a specified condition is true. Use else to specify a block of code to be executed, if the same condition is false. Use else if to specify a new condition to test, if the first condition is false.
In general it will not affect the performance but can cause unexpected behaviour. In terms of Clean Code unneserry if and if-else statements have to be removed for clarity, maintainability, better testing. One case where the performance will be reduced because of unnecessary if statements is in loops.
A switch statement is usually more efficient than a set of nested ifs. Deciding whether to use if-then-else statements or a switch statement is based on readability and the expression that the statement is testing.
Assuming simple types (in this case, I used int
) and no funny business (didn't redefine operator= for int), at least with GCC 4.6 on AMD64, there is no difference. The generated code is identical:
0000000000000000 <case_1>: 0000000000000040 <case_2>: 0: 85 ff test %edi,%edi 40: 85 ff test %edi,%edi 2: 74 14 je 18 <case_1+0x18> 42: 74 14 je 58 <case_2+0x18> 4: 83 ff 01 cmp $0x1,%edi 44: 83 ff 01 cmp $0x1,%edi 7: 74 27 je 30 <case_1+0x30> 47: 74 27 je 70 <case_2+0x30> 9: 83 ff 02 cmp $0x2,%edi 49: 83 ff 02 cmp $0x2,%edi c: 74 12 je 20 <case_1+0x20> 4c: 74 12 je 60 <case_2+0x20> e: 66 90 xchg %ax,%ax 4e: 66 90 xchg %ax,%ax 10: f3 c3 repz retq 50: f3 c3 repz retq 12: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 52: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 18: 31 c0 xor %eax,%eax 58: 31 c0 xor %eax,%eax 1a: e9 00 00 00 00 jmpq 1f <case_1+0x1f> 5a: e9 00 00 00 00 jmpq 5f <case_2+0x1f> 1f: 90 nop 5f: 90 nop 20: 31 c0 xor %eax,%eax 60: 31 c0 xor %eax,%eax 22: e9 00 00 00 00 jmpq 27 <case_1+0x27> 62: e9 00 00 00 00 jmpq 67 <case_2+0x27> 27: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 67: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 2e: 00 00 6e: 00 00 30: 31 c0 xor %eax,%eax 70: 31 c0 xor %eax,%eax 32: e9 00 00 00 00 jmpq 37 <case_1+0x37> 72: e9 00 00 00 00 jmpq 77 <case_2+0x37> 37: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 3e: 00 00
The extra instruction at the end of case_1 is just for padding (to get the next function aligned).
This isn't really surprising, figuring out that p isn't changed in that function is fairly basic optimization. If p could be changed (e.g., passed-by-reference or pointer to the various do_…
functions, or was a reference or pointer itself, so there could be an alias) then the behavior is different, and of course the generated code would be too.
In the former case conditions after the one matched are not evaluated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With