具体问题具体分析吧。
* p = 1
对这个表达式的求值包括值计算和副作用。值计算是计算这个赋值表达式的值,副作用是将1赋给左值 * p ;
要求值这整个表达式,需要先求值子表达式 * p 和 常量表达式 1 ;
要求值表达式 * p,需要先求值子表达式 p ;
表达式 * p 求值的结果是一个左值。But,你会说,不是说左值不求值吗,,
我确实不太赞同这样说,但事实就是,标准里强调:
“Evaluation of an expression in general includes both value computations and initiation of side effects.Value computation for an lvalue expression includes determining the identity of the designated object.”
,确实我会问:之前不是说了左值不求值吗? 但是现在按照标准,又属于求值了。好复杂。
那么 a=1 这个如果按照标准,表达式a也算求值了吧,也是得到被指向的那个对象。但是标准又说:
In the abstract machine, all expressions are evaluated as specified by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced (including any caused by calling a function or through volatile access to an object).
我认为标准说得非常清楚。比如语句
x = y;
要求值y,但是整个表达式 x = y 的求值只有副作用,不进行值计算,因为值计算的结果就是计算了也被丢弃;再比如语句
f (x = y);
表达式 x = y 的求值既有副作用,也有值计算,因为它的值要被传递给函数 f。再比如
sizeof (x = y)
表达式 x = y 的求值是不进行的:既不发起副作用,也不进行值计算,因为 sizeof 运算符只抽取操作数的类型,如果不求值就可以得到操作数的类型,则不会求值。因此,
int x = 0, y = 1;
printf ("%zu\n", sizeof (x = y));
printf ("%d\n", x);
打印的结果是
4
0