关于性能:C / C ++:GOTO是否比WHILE和FOR快? 您所在的位置:网站首页 memset和for循环哪个快 关于性能:C / C ++:GOTO是否比WHILE和FOR快?

关于性能:C / C ++:GOTO是否比WHILE和FOR快?

2024-07-11 16:26| 来源: 网络整理| 查看: 265

我知道,每个人都讨厌GOTO,没有人推荐它。 但这不是重点。 我只想知道,哪个代码最快?

goto循环

1234int i=3; loop: printf("something"); if(--i) goto loop;

while循环

1234int i=3; while(i--) {     printf("something"); }

for循环

123for(int i=3; i; i--) {     printf("something"); }

相关讨论 您已经编写了所有代码...为什么不对它进行概要分析? @BrianRoach:概要分析是什么意思?是的,我可以运行此循环1亿次,然后看看其中哪一个是最快的....但是我想知道通用的答案,不仅对于我的编译器和处理器。 @Mahesh:你是什么意思?循环,不进入循环?它和一些很酷的ASM指令有关吗? 测量所需的时间。让您的循环执行N次(说1000次),并测量每个循环需要多长时间。 @Mahesh:再看一遍。有一个条件,仅i。它与i!=0相同,但速度更快。 @BrianRoach:每个循环只有1-2条汇编指令的差异...测试不会是最优的,因为还有其他一些进程同时运行....唯一的可能性是在测试过程中禁用并行进程,禁用处理器中断..到目前为止,对我来说太困难了:) @Mahesh:i应该从3开始,而不是0! @Arturr:条件i和i!=0与编译器完全相同-都不是更快。 @Arturr没有一个普遍的答案。由于循环在功能上是相同的,因此您的问题恰恰是编译器将如何处理它们。就像Gabe在下面说的那样,您希望一个合理的编译器为您提供所有三个循环相同的汇编代码。但是,它并不需要这样做,并且您可以编写一个编译器,使编译器毫无理由地使其中一个循环慢得多。 为什么不看汇编器,看看哪个效率更高? 它们极有可能全部编译为同一程序集,并执行cmp和jmp增量。或者(使用给定的示例)在-O0之后的任何级别上,最终都将仅直接调用printf()3次。 对于这个严重误导的问题,我很愿意将其设为-1,但这不是您的错。但是现在以您的态度,-1。没关系。选择正确的代码,让编译器完成工作,完成一天的工作。如果它是由探查器报告的问题,请查看该程序集,看看是否可以修复它,请不要尝试进行荒谬的概括。最后,goto并不坏,"因为有个聪明的人这么说",他说这是因为它不好。您对这些建议的粗鲁态度是毫无根据的;与goto句号相比,有更好的方式表达您的意图。 用循环内的printf来问这样的问题很荒谬。与循环控制相比,您的printf将花费更多数量级的时间。在控件本身的处理变得有意义之前,您确实必须在循环内有一些非常优化的代码(没有缓存未命中之类的东西)。 还有一个侧面的评论是"仅仅因为有一些聪明的人,才这么说"。那个聪明的人是CS的创始人之一,他之所以出名是因为他敢于说在一个全是FORTRAN和计算goto的环境中。您的陈述就像说E = m c^2之所以出名一样聪明,因为爱因斯坦说过。反之亦然。 @Jens:我喜欢您对printf的评论。我不喜欢您对goto的评论:-) Dijkstra从未说过要归因于他的内容-他的编辑才是他的头衔。我相信Dijkstra希望人们动用头脑,但这对编辑来说太微妙了。 ++不是因为这是一个很好的问题,而是对StackOverflow的欢迎。我的第一个问题也不是那么好。世界各地有很多聪明的人互相帮助,很高兴您愿意加入他们的行列。 @迈克,我不知道有关" got是有害的"论文的标题。 我只是不喜欢OP谴责Messenger的态度。 无论如何,Dijkstra都强调了其内容的重要意义,即不应以无法预测的方式弄乱控制流。 就像您说的那样,他希望人们思考并倾听他必须说的话。 @Jens:我必须承认,我在SO上发表了近一期的海报,其效果是"被认为有害的探查者",只是其中的几个还不错,尤其是我希望看到人们动脑筋 关于这个主题,而不仅仅是接受标题作为他们的宗教信仰,或者至少我不会给他们一个宗教信仰。 @迈克:仅仅因为有人不同意你,并不意味着我们就把头条当做宗教,那就是阿斯宁。 有时,头条新闻是正确的。

一般来说,for和while循环被编译为与goto相同的东西,因此通常不会有什么不同。如果您有疑问,可以随时尝试全部三个,并查看花费更长的时间。奇怪的是,即使循环十亿次,您也无法测量差异。

如果您看这个答案,您会发现编译器可以为for,while和goto生成完全相同的代码(仅在这种情况下没有条件)。

相关讨论 在某些情况下,引用答案中的否条件可能对断言至关重要,因为否则goto版本可能会转换为条件测试,后跟无条件分支而不是直接条件分支。

编写简短的程序,然后执行以下操作:

123gcc -S -O2 p1.c gcc -S -O2 p2.c gcc -S -O2 p3.c

分析输出,看是否有任何区别。确保引入某种程度的不可预测性,以使编译器不会对程序进行优化。

编译器在优化这些琐碎的问题上做得很出色。我建议不要担心,而应该专注于使您成为程序员的更高效率的方面。

速度和效率是一件令人担心的大事,但是99%的时间都涉及使用正确的数据结构和算法...而不用担心for的速度是否快于while或goto,等等

我唯一一次看到goto的论点是在W. Richard Stevens的文章或书中。他的观点是,在代码的时间非常紧迫的部分(我相信他的示例是网络堆栈),可以使用goto重做嵌套有相关错误处理代码的if / else块,从而产生重要的区别。

就我个人而言,我还不够一名程序员来与史蒂文斯的工作抗辩,所以我不会尝试。 goto对于与性能相关的问题可能很有用,但是这种限制非常严格。

相关讨论 与循环构造相比,OP询问的是goto,而不是循环构造。 是的...您的答案就在眼前。 我(从内存中授予)挖了goto与我见过的其他构造的唯一相关讨论。 我的最后一句话就是答案的关键。 我不希望它是公认的答案,但我相信它与一般的讨论有关。 当您要优化某些代码时,这是一个很好的做法,在速度更为重要的极端情况下,我都可以使用它。 但是无论如何,如果可以的话,我会投赞成票。

它可能同时是编译器,优化器和体系结构特定的。

例如,代码if(--i) goto loop;是一个条件测试,后跟一个无条件分支。编译器可能只是生成相应的代码,或者可能足够聪明(尽管没有那么多智能的编译器可能不值钱),才能生成一条条件分支指令。另一方面,while(i--)在源代码级别已经是条件分支,因此,无论编译器实现或优化程序的复杂程度如何,转换为机器级别的条件分支都更加容易。

最终,差异很小,只有在需要大量迭代的情况下才有意义,并且您回答此问题的方式是为感兴趣的特定目标和编译器(和编译器设置)构建代码,并且检查生成的机器级别代码或直接测量执行时间。

在您的示例中,循环中的printf()在任何情况下都将主导任何时序;循环中更简单的操作将使观察差异变得更加容易。我建议一个空循环,然后声明i volatile以防止循环被优化为空。

所有循环和goto之间不应有任何显着差异。除了这个想法,编译器可能根本不会尝试优化GOTO。

尝试在循环中优化编译器生成的内容没有太多意义。在循环内优化代码,或减少迭代次数等是更有意义的。

相关讨论 +1表示观察到最重要的是优化循环的内部。

只要您生成与普通循环相同的控制流,几乎无论您使用for,while等,几乎任何体面的编译器都可以并且将生成相同的代码。

使用goto可以使您有所收获,但通常只有在生成正常循环根本无法(至少是干净地)无法实现的控制流时,才可以。一个典型的示例是跳入循环的中间以获取一个循环和一半的构造,而大多数语言的常规循环语句(包括C语句)并不能干净地提供这些循环。

我认为在正常条件下,编译器后会有一些代码。

实际上,我认为goto有时很方便,尽管很难阅读。

goto循环:

12345678910start_Chicken: {     ++x;     if (x >= loops)         goto end_Chicken; } goto start_Chicken; end_Chicken: x = 0;

对于循环:

1234for (int i = 0; i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有