我看不懂C99中的一些句子
Posted
技术标签:
【中文标题】我看不懂C99中的一些句子【英文标题】:I can not understand some sentences in C99 【发布时间】:2013-10-02 17:21:53 【问题描述】:在 C99 6.5 中说:
在前一个序列点和下一个序列点之间,一个对象应该有它的 表达式的评估最多修改一次存储的值。 此外,应仅读取先验值以确定该值 储存起来
“此外,应仅读取先验值以确定要存储的值”是什么意思?在 C99 中,为什么 a[i++] = 1
是未定义的行为?
【问题讨论】:
见this、this和this,甚至可能是this。 @PascalCuoq,你可以把它变成一个答案。这可能是解释序列点的一个很好的例子。 @s.bandara 各种linked问题已经很详细地解释了。 语言规范是编程语言的法律术语,它们也很有趣。也就是说,不是很多。 OP还特别询问,“此外,应仅读取先验值以确定要存储的值”可能是什么意思。 【参考方案1】:a[i++] = 1
已定义(除非除了副作用的顺序之外还有其他未定义的原因:越界访问或未初始化的i
)。
您的意思是a[i++] = i
,这是未定义的行为,因为它在与i++
相同的序列点之间读取i
,这会改变它。
“此外,应仅读取先前值以确定要存储的值”部分表示允许i = i + 1;
,尽管它从i
读取并修改了i
。
另一方面,a[i] = (i=1);
是不允许的,因为尽管只向i
写入一次,但从i
读取的内容并不是为了计算要存储的值。
【讨论】:
【参考方案2】:“应仅读取先验值以确定要存储的值”的措辞无疑是违反直觉的;为什么读取值的目的很重要?
这句话的重点是要求哪些结果取决于哪些操作。
我会从 Pascal's answer 那里窃取示例。
这个:
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
并不能确定该值。
我怀疑这种混淆是 ISO C 标准 2011 年修订版(以 N1570 的草案形式提供)重新措辞该部分的原因。标准还是有序列点的概念,但是6.5p2现在说:
如果标量对象的副作用相对于其中任一对象而言是未排序的 对同一标量对象或值的不同副作用 使用相同标量对象的值进行计算,行为是 不明确的。如果有多个允许的排序 表达式的子表达式,如果这样的表达式的行为是未定义的 任何排序都会出现未排序的副作用。
第 1 段明确说明了仅在 C99 中隐含的假设:
运算符的操作数的值计算是有序的 在算子结果的值计算之前。
第 5.1.2.3 节第 2 段解释了 sequenced before 和 sequenced after 关系。
【讨论】:
我对@987654338@ 感到困惑是否意味着b = a++;
意味着a
的增量发生在a++
评估为a
之前?
@ajay: 不。a++
做了两件事:它计算一个值(比 a
的前一个值大 1),它具有修改 a
的副作用。副作用不是“价值计算”的一部分。赋值对b
的修改只有在确定a++
产生的值之后才能发生,但是赋值对b
的修改和++
对a
的修改可能发生在顺序(或并行)。以上是关于我看不懂C99中的一些句子的主要内容,如果未能解决你的问题,请参考以下文章
apache和iis共用端口怎么弄啊?搜的东西我看不懂,有谁可以qq:519963851,多谢!!!
收藏 | 15 个你非了解不可的 Linux 特殊字符,妈妈再也不用担心我看不懂这些符号了!
java for循环怎样写出1-10!的和啊,求详细说明,我看不懂