1。
if(flag == 1)
{
.....
}
else if(flag == 2)
{
.....
}
else if(flag == 3) // true condition
{
.....
}
或
2.
if(flag == 1)
{
.....
}
if(flag == 2)
{
.....
}
if(flag == 3) // true condition
{
.....
}
如果要执行上一次if
。
答案 0 :(得分:6)
我的测试显示第二个版本比前一个版本短4个指令,但优化版本长度相同:
我测试
代码:
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
优化
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测试
代码:
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
优化
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测试由Linux 3.2.14-1-ARCH x86_64 Intel(R)Core(TM)i5 CPU M 480 @ 2.67GHz上的gcc版本4.7.0 20120324(预发布)(GCC)编译。
编辑:正如@Als所建议的那样,我会给出基本优化版本(GCC中的-O
标志)。
答案 1 :(得分:5)
它们在逻辑上并不等同
一旦找到匹配条件,首先不会检查其他if
条件
无论先前的匹配如何,第二次检查每个if
条件。
如果你在第二种情况下在return
块中使用if
语句,那么它们在逻辑上是等价的。我相信同样高效。
但是,您需要在您的环境中对它们进行分析以确定。
答案 2 :(得分:2)
从技术上讲,您提供的两个代码段并不相同,因此比较它们没有意义。
可能在第二个样本中将执行多个if
块,而第一个块只能保证通过块的一个执行路径。所以在这一点上,如果你认为平均不止一个条件会成功,可以说第一个会更快地执行。
但是,如果你假设只有一个路径会执行,那么除非你知道你的编译器如何将这个代码转换成汇编,否则不再可能确定地说,因为汇编没有条件原始的(即if-else
)。
汇编语言使用Compare
,Jump if less than zero
和Jump if zero
等指令来实现条件逻辑。在没有意识到相关优化的情况下,编译器可能会无法确定哪个执行速度会更快。
答案 3 :(得分:0)
同时;如果第一个if
条件为真,那么代码的第一个块将快速执行。
答案 4 :(得分:0)
逻辑上,代码片段并不等同于它。例如,第一个说
if (a==0)
{
}
else if (a < 10)
{
}
else if (a > 10)
{
}
第二个是
if (a ==0)
{
}
if (a < 10)
{
}
if (a > 10)
{
}
以上是一个非常简单的例子。但是,如果你试图比较if
- 语句的执行时间,假设它们在逻辑上是等价的,那么第一个语句会更快,因为永远不会执行else
语句。在第二种情况下,无论先前的if
语句如何,都将评估if
条件。
答案 5 :(得分:0)
只是添加到@ Haulet的帖子,这是我在使用优化进行编译时得到的结果:
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
如您所见,标签已经过重新标记(L8 -> L9, L9 -> L10, L10 -> L3
),但代码大致相同(功能差异除外)。
我用
编译gcc-4.7 -S -O3 -march=k8 -x c -