【问题标题】:Which order functions would be called [duplicate]哪些订单函数将被称为[重复]
【发布时间】:2013-12-24 06:40:52
【问题描述】:

在下面的表达式中调用函数是否有明确的顺序,或者它是否因编译器而异?

以下规则是否适用于此处 - 在 C 中,函数的参数和大多数运算符的操作数的计算顺序是未指定的。在这个wiki page中找到了上述规则

a = (f1(10, 20) * f2(30, 40)) + f3()

【问题讨论】:

  • @Mat - 感谢您指出这一点。是的,这确实是一个重复的问题

标签: c function-calls


【解决方案1】:

该规则确实适用。 f1f2f3 可以按任何顺序进行评估。

为了稍微解释一些混乱(因为人们不断发布错误答案),运算符优先级影响事物的评估顺序 。举个例子:

f1() * f2() + f3()

现在,我们知道是的,f1()f2() 的结果相乘,然后与f3() 的结果相加,但我们不知道 求值顺序。解析树如下所示:

        +
      /   \
     *    f3()
   /   \
f1()   f2()

但我们不知道是先评估+ 的左侧还是右侧。它可能是任何一种方式。与* 相同:我们不知道是先评估它的左侧还是右侧。

编译器可以调用f3(),然后存储结果,然后调用f2(),存储结果,然后调用f1(),然后使用存储的结果进行实际计算。

或者,或者,它可以调用f1(),存储结果,然后调用f2(),然后使用这两个值相乘(然后存储该结果),然后调用f3()并完成计算。

在每种情况下(或评估顺序的任何其他排列),函数以不同的顺序进行评估,但得到相同的答案。

总结:运算符优先级决定了解析树,不是评估顺序。解析树的求值顺序未指定。

【讨论】:

  • operator precedence determines the parse tree, not the order of evaluation 不管解析树是如何形成的,编译器仍然可以以任意顺序评估函数 f1()、f2() 和 f3()。未指定表示未指定。解析树不能证明或反驳任何东西。
  • @BlueMoon:嗯?我就是这么说的。 “分析树的评估顺序未指定。”我进行“运算符优先级决定解析树”的全部原因是因为人们不断发布错误的答案,暗示运算符优先级决定了评估的顺序。我告诉人们这是不正确的,运算符优先级有不同的存在原因(确定解析树),而不是评估顺序。
  • 你是这么说的。但是你也在分析树上说一些与问题无关的东西。
  • @BlueMoon:没错,是的,因为人们一直声称解析树是相关的,而我试图向人们证明它不相关。在我发布这篇文章之前,你真的应该看到这里所有的错误答案。它可能有助于使上下文更清晰。
  • 对不起...如果这是对其他事情的回应,我会在这里停下来!
【解决方案2】:

编译器可以按任何顺序调用这些函数(也就是说,唯一的保证是 f1 和 f2 在乘法之前调用,并且所有三个都在加法之前调用,并且所有三个只会在值之后调用他们的论点是已知的)。

使用这样的文字参数,编译器可能会尽早调用它们(如上面的行和行),甚至使它们内联。

最重要的是,不要将运算符优先级与函数求值的顺序混淆。

你所知道的是,函数将在它的参数值已知之后,但在使用它的返回值之前被调用。

【讨论】:

    【解决方案3】:

    可以按任何顺序评估这些函数。没有指定的规则。先评估f1,然后评估f2,然后评估f3f3,然后评估f2,然后评估f1f2,然后评估f1,然后评估f3或什至f1 首先被评估,然后是f3,然后是f2(这里总共有六个组合!)。

    这里需要注意一点:运算符优先级与求值顺序无关

    但请记住,这些函数的求值顺序是对表达式的算术运算

    a = (f1(10, 20) * f2(30, 40)) + f3() 
    

    将根据运算符优先规则取宫殿,即首先发生f1*f2(此时必须评估f1f2),然后将其结果添加到f3(所有f1f2f2 必须被评估)。

    【讨论】:

    • 见我回答的底部。
    • 理论上,f3 甚至可能在中间——但我看不出任何有用的理由。 (好吧,取决于平台和注册使用情况和其他情况,即使这可能是相关的......)
    • @FiddlingBits;我没有对您的答案投反对票,但您答案的第一行是错误的,我认为这会诱使用户投反对票。
    • @glglgl;为什么要投反对票?
    • @hacks 是什么让你认为我做到了?我什至支持你!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    • 2011-05-02
    • 2018-04-01
    • 2014-10-16
    • 1970-01-01
    相关资源
    最近更新 更多