操作符的属性
复杂表达式的求值有三个影响的因素。
1.操作符的优先级
2.操作符的结合性
3.是否控制求值顺序。
有问题的表达式,要注意避免
表达式的求值部分由操作符的优先级决定。
表达式1
a * b + c * d + e * f
注释∶代码1在计算的时候,由于 * 比 + 的优先级高,只能保证 * 的计算是比 + 早,但是优先级并不能决定第三个 * 比第一个 + 早执行。
所以表达式的计算机顺序就可能是∶
- a * b
- c * d
- a * b + c * d
- e * f
- a * b + c * d +e * f
或者:
- a * b
- c * d
- e * f
- a * b + c * d
- a * b + c * d + e * f
表达式2
c + --c;
注释:同上,操作符的优先级只能决定自减–的运算在+的运算的前面,但是我们并没有办法得知,+操作符的左操作数的获取在右操作数之前还是之后求值
(即在准备进行+运算时,左边的c不能保证是右边–c之前的值,还是–c之后的值),所以结果是不可预测的,是有歧义的。
表达式3
#include <stdio.h>
int main()
{
int i = 0;
i = i-- - --i * (i = -3) * i++ + ++i;
printf("i = %d\n", i);
return 0;
}
这个表达式在不同的编译器上会出现不一样的结果,应该避免这样的写法
表达式4
#include <stdio.h>
int fun()
{
static int count = 1;
return ++count;
}
int main()
{
int answer;
answer = fun() - fun() * fun();
printf("%d\n",answer); //输出多少?
return 0;
}
这个代码也是有问题的,因为fun()里的count变量是static,所以每次fun返回值不一样,第一次返回2,第二次返回3,第三次返回4,因为fun() - fun() * fun()表达式只能保证 * 比 - 先运算,但每一个fun()的赋值是不确定的,有可能是2 - 3 * 4 = -10,有可能是4 - 2 * 3 = -2
表达式5
#include <stdio.h>
int main()
{
int i = 1;
int ret = (++i) + (++i) + (++i);
printf("%d\n", ret);
printf("%d\n", i);
return 0;
}
尝试在Linux环境gcc编译器,VS2019环境下都执行,分别查看结果。
VS :结果12:先算三个++i,i变成了4,最后相加4 + 4 + 4 = 12
gcc :结果10:先算第一和第二个++i,然后相加,最后算第三个++i,再相加3 + 3 + 4 = 10