【问题标题】:rate ++a,a++,a=a+1 and a+=1 in terms of execution efficiency in C.Assume gcc to be the compiler [duplicate]就C中的执行效率而言,率++a,a++,a = a + 1和a + = 1。假设gcc是编译器[重复]
【发布时间】:2011-04-03 05:13:22
【问题描述】:

可能重复:
Is there a performance difference between i++ and ++i in C++?

就以下的使用而言,请以C语言的执行时间来评价。 在一些采访中,有人问我应该在这些变体中使用哪一个以及为什么。

a++
++a
a=a+1
a+=1

【问题讨论】:

  • 你真的认为你应该根据效率来回答吗?另外,您的标题和问题不同意。我正在猜测并编辑它。
  • 这是 C 还是 C++?因为在 C++ 中,你不能假设 a++ 和 a+=1 是相同的操作(或者如果第一个存在,另一个甚至会存在)。
  • 我发现这里有大量的答案,都在 2 (!) 分钟之内,很有趣。我们都是同一个触发问题的受害者吗?
  • -1 表示白痴。如果您不使用结果,它们在任何未损坏的编译器上都是相同
  • 为了将来参考,标题中命令式的使用真的让我很紧张。 不要告诉我该怎么做,问个问题。

标签: c++ c


【解决方案1】:

这是g++ -S 产生的结果:

void irrelevant_low_level_worries()
{
    int a = 0;
//  movl    $0, -4(%ebp)

    a++;
//  incl    -4(%ebp)

    ++a;
//  incl    -4(%ebp)

    a = a + 1;
//  incl    -4(%ebp)

    a += 1;
//  incl    -4(%ebp)
}

因此,即使没有任何优化器开关,所有四个语句都会编译为完全相同的机器代码。

【讨论】:

  • @NullUserException:错误,不,他关闭了优化。 +1
  • a 设为全局变量,然后它就不会被优化掉。
  • @Null: a 正在递增,因此不会被优化掉。如果使用(a++)或(++a),则情况不同,无法比较。这个问题主要是针对“for (int i = 0; i
  • @Null:您是在谈论使用a++++a 作为更大表达式的一部分吗?但是衡量性能是无关紧要的,因为这两个表达式会产生不同的结果......
  • Fred,我们可以通过在一个比较中使用 < 和在另一个比较中使用 <= 来使它们具有可比性。
【解决方案2】:

您无法评价 C 语言中的执行时间,因为执行的不是 C 代码。您必须分析使用特定计算机上运行的特定编译器编译的可执行代码才能获得评级。

此外,对单个操作进行评级并不能为您提供真正可以使用的东西。今天的处理器并行执行多条指令,因此操作的效率在很大程度上取决于它与周围代码中的指令的配对程度。

因此,如果您真的需要使用性能最好的那个,您必须对代码进行剖析。否则(大约 98% 的时间),您应该使用最易读且最能传达代码正在做什么的那个。

【讨论】:

  • 翻译:这是一个愚蠢的问题,没有任何有意义的答案。
  • @Steven Sudit:这不是一个愚蠢的问题,而是毫无意义且过时的问题。这个问题基于 10 年前的相关条件,但今天的硬件和编程文化完全不同地关注您如何编写代码。
  • 我明白你的意思,但我不确定我是否同意。即使在低 MHz 范围内 C 编译器和处理器速度优化不佳的时代,这个问题也没有太大价值。
  • @Steven Sudit:是的,你说得对,这个问题从来就没有多大价值,但曾几何时,至少可以确定每条指令在给定计算机上需要多长时间。
  • 确实如此。现在,正如您所指出的,我们只能在给定的上下文中讨论平均时间,然后只能在给定的计算机上讨论。我曾经能够喋喋不休地说出一个操作需要多少(最佳情况)时钟周期,但这变得有点毫无意义。
【解决方案3】:

这类事情实际上很重要的情况非常罕见,介于两者之间的情况很少。大多数时候,这根本不重要。事实上,我敢打赌,你就是这种情况。

适用于一种语言/编译器/架构的东西可能不适用于其他语言。事实上,无论如何,事实与大局无关。知道这些事情并不会让你成为更好的程序员。

您应该学习算法、数据结构、渐近分析、简洁易读的编码风格、编程范式等。这些技能对于生成高性能和可管理的代码比了解这些低级细节更重要。

不要过早优化,也不要微优化。寻找全局优化。

【讨论】:

    【解决方案4】:

    这取决于a 的类型以及执行的上下文。如果a 是原始类型,并且如果所有四个语句具有相同的效果,那么就效率而言,它们都应该是等效的和相同的。也就是说,编译器应该足够聪明,可以将它们翻译成相同的优化机器代码。当然,这不是必需的,但如果您的编译器不是这种情况,那么这是开始寻找更好的编译器的好兆头。

    【讨论】:

      【解决方案5】:

      对于大多数编译器,它应该编译成相同的 ASM 代码。

      【讨论】:

        【解决方案6】:
        【解决方案7】:

        我看不出为什么执行时间应该有任何差异,但让我们证明我错了。

        a++
        

        ++a
        

        但是不一样,但这与效率无关。

        当涉及到单个行的性能时,上下文总是很重要的,猜测不是一个好主意。测试和测量更好

        【讨论】:

        • 是的,和效率有关。使用++a,我们只需增加 a 并返回新值。对于a++,要么我们必须将a 存储到寄存器中,然后递增a,然后返回寄存器中的值,要么我们必须递增a 并返回减去1 的新值。如果您不使用返回值,这显然会被优化掉。
        【解决方案8】:

        在面试中,我会给出两个答案:

        1. 乍一看,生成的代码应该非常相似,尤其是如果 a 是整数。
        2. 如果执行时间绝对是一个已知问题 - 您必须使用某种探查器对其进行测量。

        【讨论】:

        • Id modify 2) to 2') :如果执行时间确实是一个已知问题,则很可能问题出在其他地方。 2)也是如此
        【解决方案9】:

        好吧,您可能会争辩说a++ 简短而切题。它只能将a 加一,但符号很好理解。 a=a+1 有点冗长(没什么大不了的,除非你有 variablesWithGratuitouslyLongNames),但有些人可能会认为它更“灵活”,因为你可以替换 1a 中的任何一个来更改表达方式。 a+=1 可能不如其他两个灵活,但更清晰一点,因为您可以更改增量数量。 ++aa++ 不同,有些人会反对它,因为不经常使用它的人并不总是清楚。

        在效率方面,我认为大多数现代编译器都会为所有这些生成相同的代码,但我可能会弄错。确实,您必须运行具有所有变体的代码并衡量性能最佳的代码。

        (假设a是一个整数)

        【讨论】:

          【解决方案10】:

          这取决于上下文,以及我们使用的是 C 还是 C++。在 C 中,您发布的代码(a-- :- 除外)将导致 现代 C 编译器生成完全相同的代码。但很有可能预期的答案是 a++ 是最快的,而 a=a+1 是最慢的,因为古代编译器依赖于用户来执行此类优化。

          在 C++ 中,它取决于 a 的类型。当 a 是数字类型时,它的行为方式与 C 中的相同,这意味着 a++、a+=1 和 a=a+1 生成相同的代码。当 a 是一个对象时,取决于是否有任何运算符(++、+ 和 =)被重载,然后调用 a 对象的重载运算符。

          此外,当您在使用非常特殊的编译器(如微控制器或嵌入式系统)的领域工作时,这些编译器在这些输入变量中的每一个变化上都会表现得非常不同。

          【讨论】:

          • 为什么a++ 会比++a 快? :)
          • @FredOverflow,没错。答案是错误的。 ++a 将始终至少与 a++ 一样快,如果您需要返回值则更快。
          • @FredOverflow 取决于面试官的意见。
          • @FredOverflow,当a 是一个指针时,完整的表达式是total += *(a++) 或类似的,并且您在一个具有后递增间接寻址模式但没有预递增的处理器上.例如M68000。是的,在过去,我们曾经使用*(p++)*(--p),但很少使用*(++p)*(p--),因为它们与硬件中可用的寻址模式相匹配。 (事实上​​,这两个恰好与您通常想要使用指向 NUL 终止字符串或其他标记终止列表的指针相匹配,这就是为什么它们是在硬件中实现的。)
          • -1 表示性能差异很大的误导性陈述。
          猜你喜欢
          • 2017-01-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-12-17
          • 2014-09-07
          • 2012-10-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多