之间有区别吗?
if(x){
//stuff
}
和
while(x){
//stuff
break;
}
其中一个更快吗?
答案 0 :(得分:8)
逻辑上它们是一样的。编译器可能会写出相同的代码。
你应该专注于清晰的代码,而不是考虑编写混淆的代码,因为它可能会更快。
答案 1 :(得分:4)
让我们找到它:
void Test1() {
while (GetTickCount()) {
printf("Hello World Test1");
break;
}
}
void Test2() {
if (GetTickCount()) {
printf("Hello World Test2");
}
}
void main() {
Test1(); Test2();
}
使用 VC Nov 2013 CTP 编译为完全优化版本:
CPU Disasm
Address Hex dump Command Comments
012A12A0 /$ FF15 00302A01 CALL DWORD PTR DS:[<&KERNEL32.GetTickCou ; [KERNEL32.GetTickCount
012A12A6 |. 85C0 TEST EAX,EAX
012A12A8 |. 74 0E JZ SHORT 012A12B8
012A12AA |. 68 8C312A01 PUSH OFFSET 012A318C ; ASCII "Hello World Test1"
012A12AF |. FF15 64302A01 CALL DWORD PTR DS:[<&MSVCR120.printf>]
012A12B5 |. 83C4 04 ADD ESP,4
012A12B8 |> FF15 00302A01 CALL DWORD PTR DS:[<&KERNEL32.GetTickCou ; [KERNEL32.GetTickCount
012A12BE |. 85C0 TEST EAX,EAX
012A12C0 |. 74 0E JZ SHORT 012A12D0
012A12C2 |. 68 A0312A01 PUSH OFFSET 012A31A0 ; ASCII "Hello World Test2"
012A12C7 |. FF15 64302A01 CALL DWORD PTR DS:[<&MSVCR120.printf>]
012A12CD |. 83C4 04 ADD ESP,4
012A12D0 |> 33C0 XOR EAX,EAX
012A12D2 \. C3 RETN
如您所见,VC编译器生成相同的代码。如果禁用优化,情况就不是这样了:
<强>测试1 强>
CPU Disasm
Address Hex dump Command Comments
00F91630 /$ 55 PUSH EBP ; Playground.Test1(void)
00F91631 |. 8BEC MOV EBP,ESP
00F91633 |> FF15 0030F900 /CALL DWORD PTR DS:[<&KERNEL32.GetTickCo ; [KERNEL32.GetTickCount
00F91639 |. 85C0 |TEST EAX,EAX
00F9163B |. 74 12 |JZ SHORT 00F9164F
00F9163D |. 68 9C31F900 |PUSH OFFSET 00F9319C ; ASCII "Hello World Test1"
00F91642 |. FF15 6430F900 |CALL DWORD PTR DS:[<&MSVCR120.printf>]
00F91648 |. 83C4 04 |ADD ESP,4
00F9164B |. EB 02 |JMP SHORT 00F9164F
00F9164D |.^ EB E4 \JMP SHORT 00F91633
00F9164F |> 5D POP EBP
00F91650 \. C3 RETN
<强>的Test2 强>
CPU Disasm
Address Hex dump Command Comments
00F91660 /$ 55 PUSH EBP ; Playground.Test2(void)
00F91661 |. 8BEC MOV EBP,ESP
00F91663 |. FF15 0030F900 CALL DWORD PTR DS:[<&KERNEL32.GetTickCou ; [KERNEL32.GetTickCount
00F91669 |. 85C0 TEST EAX,EAX
00F9166B |. 74 0E JZ SHORT 00F9167B
00F9166D |. 68 B031F900 PUSH OFFSET 00F931B0 ; ASCII "Hello World Test2"
00F91672 |. FF15 6430F900 CALL DWORD PTR DS:[<&MSVCR120.printf>]
00F91678 |. 83C4 04 ADD ESP,4
00F9167B |> 5D POP EBP
00F9167C \. C3 RETN
您可以清楚地看到它们略有不同:
如果条件不满足,它们的行为完全相同(因此以相同的速度执行)
如果符合条件,则在Test1
我们必须再执行一次跳转(00F9164B
- JMP SHORT 00F9164F
)
=&GT;如果在没有优化的情况下编译代码,理论上会Test2
更快,因为编译器输出Test1
的实数循环。
这是不成熟的优化吗?的当然!强>
答案 2 :(得分:2)
在汇编程序中输出代码并查看它是否与编译器相同(更可能的是,编译器将优化两个相同的机器代码,因为它们在逻辑上是等效的)。编写可读和可维护的代码几乎总是比担心这样的细节更重要。现代编译器能够优化这样的简单案例,除了以最易读的方式编写代码之外,没有什么理由可以做任何其他事情,在这种情况下,我认为将代码编写为if
语句表示您的意图您的代码的其他读者远远优于while
+ break
组合。
答案 3 :(得分:2)
它是一样的。虽然理论上while()比if
多一个jmp
答案 4 :(得分:1)
while(x){
//stuff
break;
}
如果您只是针对给定条件执行一次操作,则上述代码似乎是不合理的。这就是为什么在这种情况下if语句更可取的原因!至于速度差异,我真的怀疑一方面的重大优势。使用while循环代替if语句是可怕的:
if(condition)
{
// do stuff
}
else if(another_condition)
{
// do stuff
}
else
{
// do stuff
}
这是使用while循环的等价物:
while(condition)
{
// do stuff
break;
}
while(!condition && another_condition)
{
// do stuff
break;
}
while(!condition && !another_condition)
{
// do stuff
break;
}
让您的团队受宠,让您的代码可读: - )
答案 5 :(得分:1)
他们有不同的目的。
if
是一个选择陈述
while
是一个迭代语句。
并且应该根据他们的目的使用它们。
答案 6 :(得分:1)
如果在第一次迭代时断开while循环,则while循环用作if语句。
但是你不应该为此目的使用while循环,因为它的目的是循环。
答案 7 :(得分:-1)
因此,以下内容可能会提供相同的内容,因为for-C由C预处理器修改为一段时间。其他人对清晰度的看法虽然......
for(;x;){
//stuff
break;
}