C 中的运算符评估顺序,它们究竟是如何工作的?

Operator evaluation order in C, how exactly do they work?

我对运算符的求值顺序有几个疑问,在第一个示例中,变量 A 和变量 B 都可以先针对此表达式执行

#include <stdio.h>

int main(void)
{
    int A = 5, B = 3;
    int c = a + b;   // Can any of the variables be executed first, 
                     // depending on the compiler ?
    return 0;
}

在这个例子中,如果函数g修改变量A可能会有副作用

#include <stdio.h>

int main(void)
{
    int A = 5, B = 3
    int c = f(A) + g(B);
    return 0;
}

比较运算符,例如 > 运算符,其操作数没有顺序?

#include <stdio.h>

int main(void)
{
    int A = 5, B = 3
    int c = f(A) > g(B);
    return 0;
}

现在再举一个例子,使用运算符 ,

#include <stdio.h>

int main(void)
{
    int A = 5, B = 3
    int c = f(A, B);
    return 0;
}

总之,我给出的这些例子,求值的顺序,会不会取决于编译器?

在 C17 6.5/3 中可以找到正式的(但非常无用的)定义:

The grouping of operators and operands is indicated by the syntax. Except as specified later, side effects and value computations of subexpressions are unsequenced.

这句蹩脚的句子正是运算符优先级和求值顺序的定义。我们可以而且应该回去阅读 C99 6.5/3,以便找到写得更好、以前规范的文本:

Except as specified later (for the function-call (), &&, ||, ?:, and comma operators), the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.

意思是一样的。 关于评估顺序,当前 C 标准的“子表达式的副作用和值计算是无序的”部分意味着对于大多数具有多个操作数(以及函数参数列表)的运算符,评估顺序是 未指定的行为.

这确实意味着顺序取决于编译器,可能没有记录,不应依赖。它甚至意味着允许同一个编译器在同一个程序中根据具体情况更改顺序!因此,给定代码 f(a) + f(b); f(a) + f(b);,如果编译器愿意,它甚至可以作为 f(a) f(b) f(b) f(a) 执行。

唯一具有明确定义的求值顺序的(非一元)运算符是 &&||?:,