下面的输出应该是什么以及为什么它应该依赖于编译器?

问题描述 投票:1回答:2

请帮助我理解输出。我们知道,我们不能说f1()在f2()之前被评估是由于“+”的左右关联性,因为仅当有2个或多于2个运算符时才会出现关联性具有相同的优先权。那么用于确定答案的概念应该是什么?

// Associativity is not used in the below program.
int x = 0; 
int f1() {
  x = 5;
  return x;
} 
int f2() {
  x = 10;
  return x;
}
int main() {
  int p = f1() + f2();
  printf("%d ", x);
  return 0;
}
c
2个回答
3
投票

这两个函数调用是不确定的顺序w.r.t。彼此。 C11 6.5.2.2p10

在评估函数指示符和实际参数之后但在实际调用之前有一个序列点。调用函数(包括其他函数调用)中的每个评估(在执行被调用函数的主体之前或之后没有特别排序)对于被调用函数的执行是不确定地排序的。

并且不确定地排序意味着C11 5.1.2.3p3

当A在B之前或之后进行测序时,评估A和B是不确定的,但未指明哪个是

因此,首先调用f1f2,并且不会交错执行函数。你可以通过检查x的值来告诉它 - 如果它是5然后f2被调用;如果10f1被称为第一。

footnote 86还说:

在程序执行期间不止一次评估的表达式中,不需要在不同的评估中一致地执行其子表达式的未序列和不确定顺序的评估。

即如果你在一个循环中这样做,在第一次迭代时可能会先调用f1,然后在下一个f2上调用它...


运算符关联性和优先级几乎与评估的实际顺序毫无关系 - 与几乎所有其他运算符一样,+操作数的评估顺序是unspecified - and unsequenced (C11 6.5p3)


3
投票

因为标准没有对其施加任何约束。

说这个的部分来自6.5

运算符和操作数的分组由语法指示.85)除了后面指出的,子表达式的副作用和值计算是不可测量的。

从标准本身6.5.2.2(显示标准不强加任何约束的示例)

在函数调用中

  (*pf[f1()]) (f2(), f3() + f4())

可以按任何顺序调用函数f1f2f3f4。在调用pf[f1()]指向的函数之前,必须完成所有副作用。

您的问题的答案将是未指定的。你不能肯定地说些什么。如果调用f1(),那么第一个结果将是某种东西,如果它是另一种方式,那么结果将是不同的。

支持我所说的检查这个link

...在表达式f(i++) + g(j++) + h(k++)中,使用f原始值的参数调用i,但i在进入f体之前递增。同样,jk分别在进入gh之前更新。但是,没有指定执行f(),g(),h()的顺序,也没有指定i,j,k的顺序递增。如果f的主体访问变量j和k,它可能既没有发现,也没有发现其中一个增加。 (函数调用f(a,b,c)不是逗号运算符的使用;未指定a,b和c的求值顺序。)

© www.soinside.com 2019 - 2024. All rights reserved.