1

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

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

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

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

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

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

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

另外,还有一句话:

赋值表达式在赋值后具有左操作数的值,但不是左值。

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

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

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

4

1 回答 1

3

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

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

它进一步说:

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

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

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

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

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

于 2021-01-16T12:20:16.543 回答