【问题标题】:Unsequenced modification warning [duplicate]未排序的修改警告[重复]
【发布时间】:2021-05-23 10:05:28
【问题描述】:

我正在读一本 C 的书,我陷入了这个例子。

作者说这个例子的结果是x == 0y == 101

我对 y 结果很好,但是我真的认为表达式中的第一件事会计算 y == y 然后会增加 y +1

我编译了代码,得到了一个警告:未排序的修改,并且 1 存储在 x 中。

这是什么原因?

int main(void)
{
    int x,y=100;
    x=y;
    x= y == y++;
    printf ("%d %d",x,y);
    return 0;
}

【问题讨论】:

  • 嗯,这是一本用我的母语写的书,英文叫“The Programming Language C in depth (5th edition)”
  • “未排序的修改”听起来像是 Clang 给出的警告。用 GCC 试试同样的方法。
  • '深度编程语言 C(第 5 版)' - 听起来像是一条指令。将重物附在书上,然后将其放入您能到达的最深的水中。 Challenger Deep 会很好。

标签: c operators


【解决方案1】:

在表达式y == y++ 中,表达式yy++ 的计算顺序是无序的,或者更简单地说,没有指定顺序。

但是,这里的结果取决于表达式的计算顺序。因此编译器会发出诊断信息。

【讨论】:

    【解决方案2】:

    C 中的表达式,包括另一个表达式的子表达式,可能有两种效果:

    • 主要作用:它产生一个值,以便在包含表达式中进一步使用。
    • 副作用:它修改对象或文件或访问易失性对象。

    一般来说,C 标准并没有说明副作用发生的时间。 不一定在评估主效应的同时发生。

    x = y == y++;中,y++有修改y的副作用。但是,y 也用作== 的左操作数。因为 C 标准没有说明副作用何时会发生,它可能发生在左侧操作数使用 y 的值之前、期间或之后。

    C 标准中的一条规则说,如果使用对象的值相对于对该对象的修改没有排序(指定发生在之前或之后),则行为未定义。此外,如果两个修改相对于彼此未排序,则行为未定义。

    此规则的最初动机是为y++ 增加y 可能需要多个步骤。在只有 16 位算术的计算机中,C 实现可能支持 32 位 int,方法是使用多条指令获取 y 的低 16 位,将它们加 1,记住进位,存储结果 16位,获取y 的高 16 位,添加进位,并存储结果位。如果其他代码分别尝试获取y 的值,它可能会在加 1 后获取低 16 位,但在加进位之前获取高 16 位,结果可能是y 既不是加法前的值(eg, 0x1ffff)也不是加法后的值(eg&, 0x20000),而是混合(0x10000)。你可以说一个实现应该跟踪对对象的操作并将它们分开,这样就不会发生这种交错。但是,这会给编译器带来负担并干扰优化。

    【讨论】:

    • 多词变量真的是未定义的动机吗?编译器似乎没有太多理由在递增一个变量的过程中坚持访问另一个变量。另一方面,编译器将x++ == y 编译成简单的“获取x 的值,递增x,获取y 的值,比较”是完全合理的,而不考虑@987654338 @ 和 y 实际上是同一个变量。而另一个人将增量踢到整个表达式的末尾。
    • @ilkkachu:如果问题仅仅是 xy 是同一对象的不同名称(如果例程传递了指针 pq 并且有表达式(*p)++ == *q),那么我们不需要行为未定义的规则,只是未指定y (*q) 的值是增量之前还是之后的值。事实上,对对象的修改可能是非原子的,这促使我们比未指定更进一步。
    猜你喜欢
    • 2017-05-31
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    • 2011-03-20
    • 2011-08-21
    • 1970-01-01
    • 2016-12-26
    • 1970-01-01
    相关资源
    最近更新 更多