【问题标题】:Is assignment x=1; always an undefined behaviour according to C17?是赋值 x=1;根据 C17,总是未定义的行为?
【发布时间】:2021-04-21 06:14:09
【问题描述】:

我正在查看 C17 的最终草案,N2176。在这里,我关心的是什么样的带有副作用的表达式会导致其行为未定义。

在标准的第 6.5 节表达式中,有第 2 段以:

如果标量对象的副作用相对于其中任一对象而言是未排序的 对同一标量对象或值的不同副作用 使用相同标量对象的值进行计算,行为是 未定义。

据我了解,表达式 x=1 的求值既会产生一个值,也会引发一个副作用,从而改变由 x 指定的对象的值。决定因素将是副作用是否以任何方式与使用 x 指定的对象的值的值计算相关。

6.5.16 赋值运算符中的描述包含这句话:

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

这不能解决整个赋值的值计算顺序和赋值的副作用。

还有一句话:

赋值表达式在 赋值,但不是左值。

指定最终值应该是什么,但不要求任何排序。而且我没有看到任何其他文字提到有关副作用和价值的排序。

我知道当写成完整的语句时 x=1;不使用赋值的值。但是,标准说该值被丢弃。这意味着好像首先对值进行评估然后丢弃,因此仍应触发未定义的行为。

标准中是否有任何其他部分使该语句行为未定义?

【问题讨论】:

  • 你在部分引用的段落中的最后一句是“更新左操作数的存储值的副作用是在左操作数和右操作数的值计算之后排序的。评估的操作数是未排序的。" - 修改最后排序。
  • @StoryTeller-UnslanderMonica:这个问题没有询问副作用相对于操作数的值计算的顺序。它询问相对于赋值表达式的值计算的副作用的顺序。例如,考虑y = (x = 1),由于副作用,它既修改了x,又“使用”x分配给y
  • @EricPostpischil - 但它不会“使用”x 分配给y。它“使用”表达式(x = 1)
  • @StoryTeller-UnslanderMonica:因此我的 this-is-not-really-what-it-means-quote-marks 和我的答案。虽然标准中的一个脚注说实现实际上可以读取x 来获取值!

标签: c language-lawyer c17


【解决方案1】:

赋值表达式的值不是使用赋值对象。这是因为x = 1 的值,比如y = x = 1,不是通过x 的左值转换获得的,而是赋值表达式的值计算,根据C 2018 6.5.16 3:

…赋值表达式在赋值后具有左操作数的值,…

它进一步说:

…赋值表达式的类型是左操作数在左值转换后的类型…

这是关于类型,而不是值,但它使用虚拟语气“would have”表示“左值转换”是虚构的;它实际上并没有发生。所以赋值表达式不是通过读取左操作数来获取它的值;它的值仅仅是运算的结果。

那里有一个脚注(115)说:

允许实现读取对象以确定值,但不是必需的,即使对象具有 volatile 限定类型。

这告诉我们,左操作数实际上可以用于计算赋值表达式的值。但是,这是一个可以通过这样做来实现的声明,而不是声明这是 C 计算模型中赋值表达式语义的一部分。

【讨论】:

    猜你喜欢
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 2014-05-01
    • 2013-03-02
    • 1970-01-01
    • 2017-12-26
    • 2022-01-14
    相关资源
    最近更新 更多