ake*_*ent 63

简答:不,他们完全一样.

猜测它理论上可能依赖于编译器; 一个真正破碎的人可能会做一些略有不同的事情,但我会感到惊讶.

只是为了好玩,这里有两个变体,使用Ubuntu附带的x86 gcc版本4.3.3编译为完全相同的汇编代码.您可以使用linux 上的objdump检查最终二进制文件上生成的程序集.

int main()
{
#if 1
    int i = 10;
    do { printf("%d\n", i); } while(--i);
#else
    int i = 10;
    for (; i; --i) printf("%d\n", i);
#endif
}

编辑:这是一个"橘子与橘子",而循环示例也编译成同样的东西:

    while(i) { printf("%d\n", i); --i; }

  • +1用于执行实验,而不只是"表达意见" (19认同)
  • 通过执行实验进行尽职调查的另一个+1.很棒的答案! (6认同)
  • -1用于比较apple(for)和oranges(do-while),它们通常不相等.您应该使用功能相当的while循环. (4认同)

Pau*_*lin 14

如果for和while循环执行相同的操作,编译器生成的机器代码应该(几乎)相同.

比如几年前我做的一些测试,

for (int i = 0; i < 10; i++)
{
...
}
Run Code Online (Sandbox Code Playgroud)

int i = 0;
do
{
  ...
  i++;
}
while (i < 10);
Run Code Online (Sandbox Code Playgroud)

将生成完全相同的代码,或者(和Neil在评论中指出)使用一个额外的jmp,这将无法在性能上产生足够大的差异而担心.

  • 实际上,在我的VC++ 6.0编译器上,它们不会生成完全相同的代码.for()verrsion生成一个额外的jmp指令. (11认同)
  • 在人们开始兴奋之前,我应该指出jmp只采用一次,无论循环的迭代次数多少.我的观点是代码不完全相同,并且应该根据经验检查这些内容. (2认同)

San*_*a R 8

没有语义差异,不需要任何编译差异.但这取决于编译器.所以我尝试使用g ++ 4.3.2,CC 5.5和xlc6.

g ++,CC是相同的,xlc不是

xlc的差异在于初始循环条目.

extern int doit( int );
void loop1( ) {
  for ( int ii = 0; ii < 10; ii++ ) {
    doit( ii );
  }
}

void loop2() {
  int ii = 0; 
  while ( ii < 10 ) {
    doit( ii );
    ii++;
  }
}
Run Code Online (Sandbox Code Playgroud)

XLC输出

.loop2:                                 # 0x00000000 (H.10.NO_SYMBOL)
    mfspr   r0,LR
    stu     SP,-80(SP)
    st      r0,88(SP)
    cal     r3,0(r0)
    st      r3,64(SP)
    l       r3,64(SP)  ### DIFFERENCE ###
    cmpi    0,r3,10
    bc      BO_IF_NOT,CR0_LT,__L40
...
enter code here
.loop1:                                 # 0x0000006c (H.10.NO_SYMBOL+0x6c)
    mfspr   r0,LR
    stu     SP,-80(SP)
    st      r0,88(SP)
    cal     r3,0(r0)
    cmpi    0,r3,10    ### DIFFERENCE ###
    st      r3,64(SP)
    bc      BO_IF_NOT,CR0_LT,__La8
...
Run Code Online (Sandbox Code Playgroud)


Pet*_*ham 7

while循环测试中变量的范围比for循环标题中声明的变量范围更宽.

因此,如果存在性能影响作为保持变量更长时间活动的副作用,那么在while和for循环之间进行选择会产生性能影响(并且不会在{}中包含while,以缩小其范围.变量).

一个示例可能是并发集合,它计算引用它的迭代器的数量,如果存在多个迭代器,它会应用锁定以防止并发修改,但如果只有一个迭代器引用它,优化就会使锁定失败.如果你for在一个函数中有两个循环,在同一个容器上使用不同名称的迭代器,则会采用快速路径,但是如果有两个while循环,则会采用慢速路径.同样,如果对象很大(更多缓存流量)或使用系统资源,可能会影响性能.但我想不出一个我见过的真正的例子,它会产生什么影响.


Run*_*odt 6

使用循环展开优化的编译器可能只在for-loop情况下这样做.


xto*_*ofl 5

两者都是等价的.这是一个语义问题.

唯一的区别可能在于做... while结构,在那里你推迟条件的评估,直到之后的身体,从而可节省1分的评价.

i = 1; do { ... i--; } while( i > 0 ); 
Run Code Online (Sandbox Code Playgroud)

而不是

for(  i = 1; i > 0; --i )
{ ....
}  
Run Code Online (Sandbox Code Playgroud)