求值
求值 (Evaluation) 讨论的是:一个表达式在运行时如何计算出结果值,以及如何产生副作用。
本节将围绕三个关键词建立正确的直觉:
- 值计算 (Value computation):得到一个结果值;
- 副作用 (Side effect):修改对象、执行 I/O、调用函数等;
- 顺序关系:哪些求值之间有确定先后,哪些没有。
1. 未求值上下文(不求值表达式)
有些语境中,表达式不会被求值,因此其中的副作用不会发生。最典型的是 sizeof:
c
#include <stdio.h>
int main(void) {
int i = 0;
(void)sizeof(i++); /* i++ 不会被执行 */
printf("%d\n", i);
return 0;
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
本章只需要记住:不要依赖“未求值上下文”中表达式的副作用。
2. 先后关系与未定义行为
很多初学者写出 UB 的根源是:在同一个表达式里,对同一个标量对象既读又改,并且两次操作之间没有标准保证的先后关系。
例如:
c
int i = 0;
int x = i++ + ++i; /* UB */1
2
2
要修复它,最直接的方法是:拆开写。
c
int i = 0;
int a = i++;
int b = ++i;
int x = a + b;1
2
3
4
2
3
4
3. 习题
#10431
⚡4⏳3
判断下面每段代码是否可能产生未定义行为 (Undefined Behavior, UB);如果是,请写出一个等价且无 UB 的版本(要求:用拆分语句的方式修复)。
c
int i = 0;
int x = i++ + i;1
2
2
c
int i = 0;
int x = ++i + 1;1
2
2