首页 > 解决方案 > 我对 C 中的优先规则有疑问

问题描述

在以下函数中:

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);
}

你会得到 sum 1 等于 46,sum 2 等于 48。如果没有优先规则,函数将如何运行?

如果没有一致的优先规则,事情会有多大的不同?

标签: cfunctionoperator-precedencerules

解决方案


优先规则告诉我们一个表达式是如何构造的,而不是它是如何计算的。在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 / 2fun(&i)先评估。事实上,C 标准中没有任何规则指定是否先评估i / 2or 。fun(&i)编译器可以选择。

如果i / 2先评估,结果将是10 / 2 + 41然后5 + 41和最后46。如果fun(&i)首先评估,结果将是14 / 2 + 41然后7 + 41和最后48。您的编译器选择了前者。它本可以选择后者。

如果没有优先规则,函数将如何运行?

如果没有规则,我们将不知道函数将如何执行。规则告诉我们它将如何执行。

一些评论断言这个程序的行为是未定义的。这是不正确的。这种误解来自 C 2018 6.5 2,它说:

如果标量对象的副作用相对于同一标量对象的不同副作用或使用同一标量对象的值的值计算是未排序的,则行为未定义......</p>

在您的代码中,i / 2使用i并包含对(通过赋值更改其值)fun(&i)的“副作用” 。i如果这些是未排序的,则行为将是未定义的。但是,在计算参数之后fun和调用它之前都有一个序列点,并且在每个完整表达式之后都有一个序列点fun,包括它的return语句。i因此,对它的使用和副作用有一些排序。这种排序不完全由 C 标准的规则确定,但按照标准的定义,它是不确定排序的,而不是未排序的。


推荐阅读