或者这全都与语义有关?

有帮助吗?

解决方案

短的答案:无,它们是完全相同的

想这可能在理论上取决于编译器;一个真正的坏人们可能会做一些稍微不同,但我会感到惊讶。

只是为了好玩这里有两个变种,我使用的x86 gcc版本4.3.3作为附带Ubuntu的那个向下编译完全相同的汇编代码。可以检查与 objdump的 Linux上的最终二进制生成的汇编

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; }

其他提示

如果你对和while循环做同样的事情,由编译器生成的机器代码应该是(几乎)是相同的。

例如,在一些测试中,我在几年前一样,

for (int i = 0; i < 10; i++)
{
...
}

int i = 0;
do
{
  ...
  i++;
}
while (i < 10);

将产生完全相同的代码,或(和尼尔在评论中指出)有一个额外的JMP,这不会使性能有很大的差异足以担心。

没有语义差异,不需要有任何编译差。但是,这取决于编译器。于是,我就用G ++ 4.3.2,CC 5.5,xlc6。

<强>克++,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++;
  }
}

<强> XLC OUTPUT

.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
...

while回路的测试的变量的范围比在for循环的头部声明的变量的范围更宽。

因此,如果有作为保持变量活得更长的副作用性能影响,则会有性能影响在for循环一段时间,一个之间进行选择(在未包裹而向上{},以减少其变量的范围)。

一个例子可能是一个并发收集,计数迭代提到它的数目,并且如果多于一个迭代中存在,它适用锁定以防止并发修改,但作为一个优化elides锁定如果只有一个迭代是指它。如果你然后有在使用相同的容器上的不同命名迭代器函数的两个for环路,快速路将采取,但是有两个while循环慢路径将采取。同样有可能会影响性能,如果对象是大(高速缓存流量),或使用系统资源。但是我不认为我见过一个真实的例子它会有所作为的。

,以优化使用循环展开将可能只在for循环的情况下这样做的编译器。

两者是相等的。这是语义的问题。

的唯一差别可能在于操作而构建体,在这里推迟条件的评估,直到主体,并且因此可以节省1的评价。

i = 1; do { ... i--; } while( i > 0 ); 

,而不是

for(  i = 1; i > 0; --i )
{ ....
}  

我写的编译器。我们编译所有的 “结构化” 控制流(ifwhileforswitchdo ... while)到有条件和无条件分支。然后,我们分析了控制流图。由于C编译器具有反正对付一般goto,它是最容易的降低的所有分支和条件分支指令,那么一定要处理这种情况良好。 (A C编译器必须做好不只是在手写代码也对自动生成的代码,其可以具有许多许多goto语句。)

没有。如果他们正在做的事情相当的,他们会编译成相同的代码 - 如你所说,它是关于语义。选择一个最能代表你想表达的东西。

在理想情况下应该是相同的,但最终它取决于你的编译器/解释器。可以肯定,必须测量或检查所生成的汇编代码。

证明可能存在的差异。这些线产生不同的汇编代码使用cc65

for (; i < 1000; ++i);   
while (i < 1000) ++i;

在爱特梅尔ATMEGA而()比对()更快。这是为什么在AVR035说明:针对AVR高效C编码

P.S。原始平台不是在问题中提到。

继续作为和<强>行为不同而:在作为下,它改变了计数器,在<强>而下,它通常不

添加另一个答案:根据我的经验,优化软件就像剃掉一个人浓密的大胡子。

  • 首先,用剪刀把它剪成大块(从调用树上修剪掉整个四肢)。
  • 然后你用电动剪刀把它剪短(调整算法)。
  • 最后用剃刀剃掉最后一点(低级优化)。

最后是两者的区别 for()while() 可能,但可能不会,产生影响。

附:我认识的程序员(他们都非常优秀,我怀疑他们是一个有代表性的样本)基本上是从另一个方向进行的。

它们是同至于性能也越高。我倾向于使用while等待状态改变(例如,等待一个缓冲器被填充)和for处理多个离散的对象时(例如,集合中的每个项目去)时。

有在某些情况下的差。

如果你在那里这种差异的重要点,您可能需要选择一个更好的算法或开始用汇编语言编码。相信我,在装配编码优选定影编译器的版本。

while() 快/慢于 for()?让我们回顾一下关于优化的一些事情:

  • 编译器编写者非常努力地通过减少对跳转、比较、增量以及它们生成的其他类型指令的调用来缩短周期。

  • 另一方面,调用指令会消耗更多的周期,但编译器几乎无法采取任何措施来删除这些指令。

  • 作为程序员,我们编写了大量的函数调用,有些是因为我们有意这样做,有些是因为我们懒惰,有些是因为编译器在不明显的情况下将它们插入了。

  • 大多数时候,这并不重要,因为硬件是如此之快,而我们的工作又如此之小,计算机就像一只小猎犬,狼吞虎咽地吃东西并乞求更多。

  • 然而,有时,工作量足够大,以至于绩效成为一个问题。

  • 那我们该怎么办呢?更大的回报在哪里?

    • 让编译器减少循环的几个周期等等?
    • 查找不存在的函数调用 -真的- 需要做这么多吗?
  • 编译器无法执行后者。只有我们程序员可以。

  • 我们需要学习或被教导如何做到这一点。它不是自然而然的。我们天生倾向于做出错误的猜测,然后押注于它们。获得更好的算法是一个开始,但仅仅是一个开始。我们的老师需要教这个,如果确实的话 他们 知识。

  • 分析器是一个开始。 我做这个。

当被问到时威利·萨顿的杜撰引言 你为什么要抢劫银行?:
因为钱就在那里。

如果您想节省周期,请找出它们在哪里。

可能只是编码风格。

  • 如果你知道迭代次数。
  • 而如果你不知道迭代次数。
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top