首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不是一个[i++]=1(1),其中计算的增量相对于数组的索引而言是未排序的,从而违反了S6.5.2

不是一个[i++]=1(1),其中计算的增量相对于数组的索引而言是未排序的,从而违反了S6.5.2
EN

Stack Overflow用户
提问于 2022-01-20 14:43:34
回答 2查看 146关注 0票数 1

问题长度的字数限制。

正如@Karl Knechtel所指出的那样,我感到困惑的是,相对于i++增量操作,没有获取数组索引的操作吗?如果没有排序,为什么C标准6.5.2一行提到(我理解的单词/短语中添加了强调,此处适用)

如果标量对象上的副作用是未排序的相对,则与对同一个标量对象的不同副作用或使用相同标量对象的值计算的值相比,行为是未定义的。

我阅读了这个问题我不能理解C99中的一些句子,其中OP试图理解为什么a[i++] = 1是未定义的。接受,也是帕斯卡·库奥克投票最多的答案之一提到,这是定义的行为。

我还试着使用-std=c99-Wall-Wextra标志以及一系列其他标志(基本上是GCC 11.2.0中启用的所有标志)编译程序,但是代码没有抛出任何警告。

然而,我的问题/困惑是,为什么这是一种明确的行为?

来自C11标准 S6.5.2

如果对标量对象的副作用相对于对同一个标量对象的不同副作用或使用同一个标量对象的值计算而言没有排序,则行为是未定义的。如果一个表达式的子表达式有多个允许的顺序,则如果在任何顺序中发生这种未排序的副作用,则该行为是未定义的。

在阅读SO上的大多数线程(使用标记[C][sequence-points])之后,我的理解/推理是,i++将导致更新i值的副作用。在这种情况下,这种副作用将不按使用同一个标量对象的值计算进行排序。我理解a[integer object]构成了value computation。那么,它应该是未定义的行为?

甚至来自C99 S6.5(p2)

此外,应只读取先验值以确定要存储的值。

我理解/理解这个表达式也应该呈现未定义的a[i++] = 1

EN

回答 2

Stack Overflow用户

发布于 2022-01-20 14:52:38

在这种情况下,这种副作用将不按使用同一个标量对象的值计算进行排序。

i++中涉及的标量对象是i。更新i的副作用与i++值的计算无关,因为C 2018 6.5.2.4 (它指定后缀增量和递减运算符的行为)第2段说:

…结果的值计算是在更新操作数…的存储值的副作用之前进行的。

C 2011年的措辞相同。(C 2018只载有对C 2011的技术更正和澄清。

甚至来自C99 S6.5(p2) 此外,应只读取先验值以确定要存储的值。

C 1999标准中的一项规则不适用于2011年或2018年的标准;它必须单独解释。在1999到2011年间,标准从孤立序列点转移到更精细的排序关系规则。

i++中,读取先验值以确定i的新值应该是什么,因此它符合该规则。

该规则试图说,标量对象的任何读取都必须在对象写入的前提链中。例如,在i = 3*i + i*i中,为了计算要写入i的值,i的所有三种读取都是必需的,因此它们必须在写入之前执行。但在i = ++i + i;中,上一学期对i的读取并不是为++ii写入的先决条件,因此它不一定在写入之前执行。因此,这将不符合规则。

…我感到困惑的是,相对于i++增量操作,没有顺序地获取数组索引的操作吗?

数组元素的读取相对于i的更新没有排序,这是可以的,因为没有规则要求对其进行排序。C 2018年6.5 2说,重点是:

如果对标量对象的副作用相对于相同的标量对象的不同副作用或使用相同的标量对象的值计算,则行为是未定义的。

数组元素是与i不同的标量对象,因此我们不关心数组元素的读取和i更新之间没有排序。

票数 4
EN

Stack Overflow用户

发布于 2022-01-20 20:23:30

非常感谢各位议员的即时回应。我试着用这种语言来回答,我理解。

在阅读了一篇关于阅读这篇文章的建议之后,用抽象树处理序列点问题 (我知道,这不规范)

让我使用抽象语法树表示ai++ =1。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70788201

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档