【问题标题】:Clarification c./ change in wording of C99 standard澄清 c./ C99 标准的措辞变化
【发布时间】:2014-07-21 05:16:27
【问题描述】:

我意识到仅仅询问未定义的行为会导致一些人投反对票,但我有一个问题比较 C99 与 2007 年 9 月(我唯一可以访问的,这对我很重要)和 2011 年的. 相关引用来自任一版本的 6.5 (2):

2007:“在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。此外,应只读先前值以确定要存储的值.(添加了突出显示)”

2011:“如果标量对象的副作用相对于同一标量对象的不同副作用或使用相同标量对象的值计算未排序,则行为未定义。(...)”

为了说明 2007 版本中的矛盾之处,举了一个例子:

i = ++i + 1;    

由于 C 将赋值始终视为表达式(无赋值语句),因此该表达式在语义上由 2 个序列点描述。很明显,两个版本都声明上述内容会导致未定义的行为。

但是,鉴于 2007 版本中突出显示的句子,我的理解是,即使是以下表达式(再次位于两个序列点之间)也会导致未定义的行为:

  ++i; // or i++;  or a = ++i;   

,显然,“要存储的值”不仅是 read('stored' 有点模棱两可,但我自然会把它当作一次读取):它是读取的,递增的,然后存储回来。不过它是按顺序排列的,而且按照 2011 年的措辞来说非常好(可能应该如此)。

是否对措辞进行了调整以解决上述问题,以使意图与描述相匹配?

注意:我意识到这在一定程度上是基于意见的,但是 (1) 最好的情况是实际参与编写标准的人看到了这一点,并且 (2) 虽然我相信我的解释是合理的/"true",如果有人有力地反对它,这也很有用。

【问题讨论】:

  • 如果能提供一些关于你在谈论什么章节/主题的线索。
  • 我提到了准确的章节 - 6.5 (2)。
  • 递增是“确定要存储的值”。
  • @RaymondChen:标准中没有定义“确定存储的值”(据我所知),整个问题是关于匹配意图和措辞。我显然同意它应该是合法的。
  • “确定存储的值”在英语中有其通常的含义:您可以加载该值,在计算中使用该值,然后存储计算结果。您不能加载该值并将其用于不相关的计算。用物理学术语来说,加载和存储必须是因果相关的。

标签: c c99


【解决方案1】:

但是,鉴于 2007 版本中突出显示的句子,我的理解是,即使是以下表达式(再次位于两个序列点之间)也会导致未定义的行为:

 ++i; // or i++;  or a = ++i;  

你理解错了。这在c-faq question-3.8 中得到了最好的解释:

....这就是第二句话的意思:如果在一个完整的表达式中写入一个对象,那么在同一个表达式中对它的任何和所有访问都必须直接参与到值的计算中写出来。该规则有效地将合法表达限​​制为那些访问明显先于修改的表达。例如,旧的备用i = i + 1 是允许的,因为i 的访问是用来确定i 的最终值的。例子

  a[i] = i++  

禁止,因为i 的访问之一(a[i] 中的那个)与最终存储在i 中的值无关(发生在i++),因此没有好的方法来定义——无论是为了我们的理解还是编译器的——访问应该发生在存储递增值之前还是之后。

i++;++i; 的情况下,i 的访问及其增量与最终存储在i 中的值有关。

【讨论】:

  • +1,是的,您的第一个突出显示的引用阐明了我的 i++ 情况;作为合法的(第二个,除其他外,因为它有一个后期增量,不太有用)。谢谢! (如果更改是为了在标准中明确,而不仅仅是在澄清的常见问题解答中,这仍然是开放的)。另外,为了确认,这是 2007 版的常见问题解答 - 无论如何,在 2011 年之前?
  • 是的。此常见问题解答基于 ISO C99。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-06
  • 2018-03-03
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
  • 1970-01-01
相关资源
最近更新 更多