【问题标题】:Precedence of Function Calls/Priority of Function Calls函数调用的优先级/函数调用的优先级
【发布时间】:2021-08-10 21:05:35
【问题描述】:
int p(int *ptrP){
    *ptrP=20;
    return *ptrP;
}

int q(int *ptrQ){
    *ptrQ=30;
    return *ptrQ;
}

int main(){
    int answer=0,a=10;
    answer=p(&a)+q(&a);      // line Alpha,for discussions sake 
    printf(" answer=%d a=%d ",answer,a ); 
}

输出:answer=50 a=30;
在 line Alpha answer=q(&a)+p(&a) 中交换函数调用导致 answer=50 a=20,这可以通过说函数调用优先级从左到右来证明,但是当我们将 line alpha 更改为 answer=p(&a)+a+q(&a); 时,输出是answer=70 a=30。
函数调用在优先级表中的位置是什么? foo()+10 和 10+foo 是等效的语句吗?

【问题讨论】:

  • 在您修改后的带有 3 个操作数的行中,答案与从左到右进行评估是一致的。
  • 还有,C++ 的哪个版本。 C++20改变了这方面的规则
  • 与直觉相反,这与运算符优先级无关。如果我们查看(3+5) * (6+7),没有关于是先计算(3+5) 还是(6+7) 的数学规则。这是一个关于“执行顺序”的问题。
  • 我刚刚在阅读 Herbert Schildt 的 C++ The Complete Reference,(第四版)它说 Ref(pg 52) Order of Evaluation :: Neither C nor C++ specifies the order in which the subexpressions of an expression are evaluated. This leaves the compiler free to rearrange an expression to produce more optimal code. However, it also means that your code should never rely upon the order in which subexpressions are evaluated. For example, the expression x = f1() + f2(); does not ensure that f1( ) will be called before f2( ). 这个规则是否适用于当前版本的 C 和 C++跨度>

标签: c++ function operator-precedence function-call order-of-execution


【解决方案1】:

任何表达式的任何部分的求值顺序,包括函数参数的求值顺序是未指定的(下面列出了一些例外情况)。编译器可以按任意顺序计算操作数和其他子表达式,并且在再次计算同一表达式时可以选择其他顺序。

C++ 中没有从左到右或从右到左求值的概念。不要与运算符的从左到右和从右到左的结合性混淆:表达式 a() + b() + c() 被解析为 (a() + b()) + c( ) 由于 operator+ 的从左到右的关联性,但对 c 的函数调用可以在运行时首先、最后或在 a() 或 b() 之间进行评估

更详细的解释见引用来源:https://en.cppreference.com/w/cpp/language/eval_order

所以,在你的情况下

answer=p(&a)+q(&a);

第一个执行的函数可能是p 或q。

这里也适用这条规则:

  1. 在另一个函数调用之前或之后未排序的函数调用是不确定排序的(程序必须表现得好像构成不同函数调用的 CPU 指令没有交错,即使函数是内联的)。

这意味着对p 和q 的调用,即使是内联的,也无法以允许它们交错的方式进行优化。

【讨论】:

  • 这不是 UB。您最后的报价是针对 C++98 的,这里是 the one 针对 C++11 和更高版本。
  • @HolyBlackCat 是的。我忽略了“序列点规则(直到 C++11)”部分的标题。我会编辑他的答案。
猜你喜欢
  • 2014-07-04
  • 1970-01-01
  • 2020-06-29
  • 1970-01-01
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
  • 2023-04-09
  • 2011-12-29
相关资源
最近更新 更多