在下面的函数中。
int fun(int *k) {
*k += 4;
return 3 * (*k) - 1;
}
void main() {
int i = 10, j = 10, sum1, sum2;
sum1 = (i / 2) + fun(&i);
sum2 = fun(&j) + (j / 2);
}
你会得到和1等于46, 和2等于48。如果没有优先规则,函数会如何运行?
如果没有一致的优先规则,事情的运行会有多大的不同?
先例规则告诉我们一个表达式是如何进行的 结构化而不是如何 受评. 在 sum1 = (i / 2) + fun(&i);
这些规则告诉我们的事情包括
i / 2
因为它在括号里,所以被归为一组;它不能形成,例如: (sum1 = i) / 2 + fun(&i);
.(i / 2)
和 fun(&i)
归为一类,因为 +
优先于 =
,使 sum1 = ((i / 2) + fun(&i);
而非 (sum1 = (i / 2)) + fun(&i);
.先例规则没有告诉我们是否 i / 2
或 fun(&i)
是先评估的。事实上,在C标准中,没有任何规则规定是否要先执行 i / 2
或 fun(&i)
是先评估的。编译器可以选择。
如果 i / 2
先评估,结果将是 10 / 2 + 41
然后 5 + 41
最后 46
如果 fun(&i)
先评估,结果将是 14 / 2 + 41
然后 7 + 41
最后 48
. 你的编译器选择了前者。它可以选择后者。
如果没有优先规则,函数将如何运行?
如果没有规则,我们将不知道函数将如何执行。规则是告诉我们它将如何被执行的。
有些评论断言,这个程序的行为是未定义的。这是不正确的。这个误解来自于C 2018 6.5 2,它说。
如果一个标量对象上的侧效应与同一个标量对象上的不同侧效应 或使用同一个标量对象的值进行的值计算无关,那么这个行为就是未定义的... ...
在你的代码中。i / 2
用途 i
和 fun(&i)
含有 "副作用 "的 i
(通过赋值改变其值)。如果这些都是无序的,行为将是未定义的。然而,在评估参数到 fun
并在调用它之前,在每一个完整的表达式之后都有序列点,在 fun
包括其 return
语句。因此,在使用过程中,对 i
以及对它的副作用。这种排序是不完全由C标准的规则决定的,但按照标准的定义,它是不确定的排序,而不是不排序。