当前位置: 首页 > 知识库问答 >
问题:

是否i=x[i];导致未定义的行为?

祁和通
2023-03-14

有人能解释一下< code>i = x[i]吗;导致未定义的行为?

注意:x[i]i不是易失性的,x[i]不重叠i

有C11,6.5表达式,2(强调添加):

如果标量对象上的副作用相对于同一标量对象上不同的副作用或使用相同标量对象值的值计算未排序,则行为未定义。如果一个表达式的子表达式有多个允许的排序,那么如果在任何排序中出现这种未排序的副作用,则该行为是未定义的。84)

据我所知:

  • 没有“对同一标量对象有不同的副作用”
  • 没有“使用同一标量对象的值进行值计算”

是否存在“多个允许的订单”?

总的来说:< code>i = x[i]怎么可能;被解释为序列点、副作用和未定义的行为(如果有)?

UPD。结论:< code > I = x[I];导致2个副作用:

    < li >“操作数对象的值递增”(后缀增量) < li >“更新左操作数的存储值”(赋值运算符)

该标准没有定义副作用发生的顺序。

因此,根据C11,4。一致性,2:

未定义行为在本国际标准中以“未定义行为”或省略任何明确的行为定义来表示。

实验表明,GCC/LLVM/ICC 的顺序为 1-2,而 MSVC(和其他一些)的顺序为 2-1

额外(推测):为什么不使其成为未指定的行为?示例:未指定行为的示例是副作用发生的顺序?

共有3个答案

巢德华
2023-03-14

存在使用相同标量对象的值的值计算。< code>x[i]使用< code>i的值。

从C11开始,赋值中存在序列关系。

更新左操作数的存储值的副作用在左操作数和右操作数的值计算之后排序。

(C11 6.5.16/3)

在此之前,标准讨论表达的方式是宽松的。它没有描述有序的before关系。相反,我们有:

在上一个和下一个序列点之间,对象应通过表达式的计算最多修改一次其存储值。此外,应仅读取先前的值以确定要存储的值。

“除了确定要存储的值”之外,您没有读取值,因此行为被定义

(C99 6.5/2)

应煌
2023-03-14

如果这是真的

  • 没有“对同一标量对象有不同的副作用”
  • 没有“使用同一标量对象的值进行值计算”

(在每个允许的子表达式排序中),那么您引用的规定将不会出现任何特定问题。也就是说,它的“如果”的先行词不成立,所以“如果”(未定义的行为)的结果不会被断言。

但是,对 i 既有副作用,也有使用 i 值进行值计算。前者是赋值的副作用,后者是 x[i] 的值计算。然而,这不是问题,因为对于所有形式的转让,

更新左操作数的存储值的副作用在左操作数和右操作数的值计算之后排序。

(C17 6.5.16/3)

此外,为了完整性,

运算符的操作数的值计算在运算符结果的值计算之前排序。

(C17 6.5/1)

因此,赋值对< code>i的副作用排在< code>x[i] 的值计算之后,后者排在< code>i的求值之后。

洪涵亮
2023-03-14

想象一下:

i = 3;
x[] = {1, 1, 1, 1, 1};

因此,x[i]等于1,x[i]等于2,并且x变为{1,1,2,1,1}1变成1。

为什么会有任何未定义的行为?

 类似资料:
  • 我一直在温习我未定义的行为规则,并阅读了以下内容: 未定义的行为和序列点 为什么f(i=-1,i=-1)行为未定义 为什么`x-- 在C 11中,“i = i 1”是否表现出未定义的行为? 最后有三个问题: < li >形式为< code>i=i 的术语的未定义行为规则是否适用于非整型?(表达式应翻译为< code > I . operator(I . operator(I)),由于每个函数调用都

  • 好吧,所以那里没有UB。现在我的问题是,如果将赋值运算符从更改为(或类似运算符),会发生什么。 表达式的求值是否导致未定义的行为? 在我看来,这个标准在这里似乎自相矛盾。由于的LHS仍然是一个L值(其RHS仍然是一个prvalue),就(1)和(2)而言,同样的推理也适用;在上的操作数的计算中没有未定义的行为。对于(3),复合赋值的操作(更准确地说是该操作的副作用;如果需要,它的值计算在任何情况下

  • 考虑以下C程序: null 访问易失性对象、修改对象、修改文件,或者调用执行那些操作中的任何操作的函数都是副作用,它们是执行环境状态的改变。表达式的计算通常包括值计算和副作用的启动。用于lvalue表达式的值计算包括确定指定对象的标识。 Sequenced before是单线程执行的计算之间的非对称、传递、成对关系,它导致这些计算之间的部分顺序。给定任意两个评价A和B,如果A排序在B之前,那么A的

  • 问题内容: 有人告诉我,+=效果可能与的标准符号不同i = i +。是否有与以下情况i += 1不同的情况i = i + 1? 问题答案: 这完全取决于对象i。 +=调用__iadd__方法(如果存在- 如果不存在则返回),而+调用方法1或在某些情况下调用方法2。 从API的角度来看,应该将其用于就地修改可变对象(返回已变异的对象),而__add__应该返回某些东西的新实例。对于不可变的对象,这两

  • 问题内容: 考虑以下代码段: 很明显为什么最后一行 总是会 打印:我们正在使用引用标识比较,并且一个对象 永远不会 是已经存在的对象。 问题是关于前三行:这些比较是否 保证 在原始的情况下以及自动拆箱?在某些情况下,原语将被自动装箱,并执行参考身份比较吗?(然后全部变为!) 问题答案: 是。 JLS第5.6.2节指定了二进制数值提升的规则。部分: 当运算符将二进制数值提升应用于一对操作数时,每个操

  • 问题内容: 哪个更正确?Java的结果为12或C =13。或者,如果不是正确性,请详细说明。 问题答案: 没有比这更正确的了。它实际上是未定义的,称为序列点错误。 http://en.wikipedia.org/wiki/Sequence_point

  • 问题内容: 以下Java程序平均需要0.50秒至0.55秒的时间运行: 如果我替换为,则需要0.60到0.65秒的时间来运行。怎么会? 我对该程序的每个版本运行了15次,两次交替运行。结果如下: 最快的运行时间比最慢的运行时间长。如果它们具有相同的效率,则发生这种情况的可能性将小于。 问题答案: 字节码的顺序略有不同。 : vs : 乍看之下,这没有什么区别;如果有的话,第二个版本更理想,因为它减

  • pandas中iloc()函数的参数问题 我刚刚开始学习pandas,在一份代码中出现了df.iloc[[1][0]](df是shape为(60935, 54)的pd.DataFrame数据类型)的调用,从代码上下文上理解df.iloc[[1][0]]应该是df的一行,但是应该如何理解[[1][0]]呢?为什么iloc[]中的参数会允许接受两个相邻的列表?iloc[]内部是如何处理的?这显然不是对