问在我的编译器下,这段代码
int i = 7; printf("%d\n", i++ * i++);打印出 49。无论求值顺序如何,难道不应该打印出 56 吗?
答后置递增和后置递减运算符确实++和--在返回先前的值之后执行它们的操作。经常被误解的是“之后”一词的含义和精确定义。不保证递增或递减会在给出先前的值后立即执行,并且在表达式的任何其他部分被计算之前执行。仅仅保证更新会在表达式被认为是“完成”之前(在 ANSI C 的术语中,下一个“序列点”之前;参见问题 3.8)的某个时间执行。在示例中,编译器选择将先前的值乘以自身,并稍后执行两个递增。
包含多个、含糊不清的副作用的代码的行为一直都是未定义的。(粗略地说,“多个、含糊不清的副作用”是指在单个表达式中递增、递减和赋值运算符(++, --, =, +=, -=, 等等)的任何组合,这些组合导致同一个对象被修改两次,或者被修改然后被检查。这是一个粗略的定义;有关精确的定义,请参见问题 3.8,有关更简单的定义,请参见问题 3.11,有关“未定义”的含义,请参见问题 11.33。)不要试图找出你的编译器如何实现这些东西,更不用说编写依赖于它们的代码(与许多 C 教材中不明智的练习相反);正如 Kernighan 和 Ritchie 明智地指出,“如果你不知道它们在各种机器上如何完成,这种无知可能有助于保护你。”
参考文献:K&R1 第 2.12 节,第 50 页
K&R2 第 2.12 节,第 54 页
ISO 第 6.3 节
H&S 第 7.12 节,第 227-9 页
CT&P 第 3.7 节,第 47 页
PCS 第 9.5 节,第 120-1 页