我对运算符的求值顺序有几个疑问,在第一个例子中,变量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:
操作符和操作数的分组由语法指示。除后面特别说明外,子表达式的副作用和值计算都是不排序的。
这个简单蹩脚的句子正是运算符优先级和求值顺序的定义。为了找到写得更好、更规范的文本,我们可以也应该回去阅读C99 6.5/3:
除了后面指定的(对于function-call()、&&、||、?:和逗号操作符),子表达式的求值顺序和副作用发生的顺序都是未指定的。
意思是一样的。在求值顺序方面,子表达式的"副作用"one_answers"值计算"是无顺序的;当前C标准的一部分意味着,对于大多数具有多个操作数的操作符(以及函数参数列表),求值顺序为未指定行为。
这确实意味着顺序取决于编译器,可能没有文档记录,不应该依赖。这甚至意味着同一个编译器可以在同一个程序中根据不同的情况改变顺序!因此,给定代码f(a) + f(b); f(a) + f(b);
,如果编译器喜欢这样做,它甚至可以作为f(a) f(b) f(b) f(a)
执行。
只有&&
、||
、?:
和,
(非一元)运算符有明确的求值顺序。