[英]I can not understand some sentences in C99
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算修改一次。 此外,先前的值应该只读以确定要存储的值
什么“此外,先前的值只能读取以确定要存储的值”是什么意思? 在C99中,为什么a[i++] = 1
是未定义的行为?
a[i++] = 1
被定义(除非其他原因未定义,而不是副作用的排序:超出限制的访问,或未初始化的i
)。
你的意思a[i++] = i
,这是未定义的行为,因为它在与i++
相同的序列点之间读取i
,这改变了它。
“此外,先前的值应只读以确定要存储的值”部分表示i = i + 1;
是允许的,虽然它从i
读取并修改i
。
另一方面, a[i] = (i=1);
是不允许的,因为尽管写i
只有一次,从读i
不是计算值被存储。
“先前的值应该只读以确定要存储的值”,措辞无疑是违反直觉的; 为什么值的读取目的是什么?
该句的要点是强制要求哪些结果取决于哪些操作。
我会从帕斯卡的答案中偷走一些例子。
这个:
i = i + 1;
很好。 i
在相同的表达式中读取和写入,没有中间序列点,但是没关系,因为写入在读取完成之后才能发生。 在表达式i + 1
及其子表达式i
已被完全评估之前,不能计算要存储的值。 (并且i + 1
没有可能在写入之后延迟的副作用。)该依赖性强加了严格的排序:必须在写入开始之前完成读取。
另一方面,这个:
a[i] = (i=1);
有未定义的行为。 子表达式a[i]
读出的值i
,和子表达式i=1
写入的值i
。 但是通过写入存储在i
的值不依赖于在左侧读取i
的评估,因此未定义读取和写入的顺序。 “要存储的值”是1
; 在a[i]
中读取i
并不能确定该值。
我怀疑这种混淆是为什么2011年修订的ISO C标准(草案形式为N1570 )重新措辞了该部分。 该标准仍然具有序列点的概念,但6.5p2现在说:
如果相对于对同一标量对象的不同副作用或使用相同标量对象的值进行值计算,对标量对象的副作用未被排序,则行为未定义。 如果表达式的子表达式有多个允许的排序,则如果在任何排序中发生这种未测序的副作用,则行为是不确定的。
第1段明确说明了C99中隐含的假设:
在运算符的结果的值计算之前,对运算符的操作数的值计算进行排序。
第5.1.2.3节第2节解释了之前的顺序和关系之后的顺序 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.