未定义行为和序列点

4

最近几天,我一直在试图了解未定义行为。几天前,我找到了一个C-FAQ的链接。这对于消除许多困惑非常有帮助,但当我阅读问题#3.8时,又产生了另一个大困惑。经过我许多努力理解语句(特别是第二个句子);

标准规定:

在前一个和下一个序列点之间,一个对象通过表达式的求值最多只能修改其存储值一次。此外,先前的值只能被访问以确定要存储的值。

我更愿意在SO上询问这个问题,但那里的答案都没有解释这个语句的第二句话。最后,我在那里得到了一个解释关于这一点。阅读它和FAQ多次之后,我得出结论

1. 最后一句话

此外,仅应访问先前的值以确定要存储的值

将会是这样的;

此外,仅应访问对象的先前值,以确定要存储的修改/新值(相同对象的

正如这个例子所清楚表明的那样。

 int i = 1, j, a[5];    
 i = i + 1;
 j = i + 1;
 a[i] = i; 

在表达式i = i + 1的情况下,在确定要存储的i值之前(此处为1),将访问i的先前值(即右侧操作数)。而在j = i + 1a[i] = i的情况下,i的访问值只是一个值,而不是先前值,因为这些语句中没有修改i
2.在表达式a[i] = i++a[i++] = i的情况下,上述语句的第一句话:在前一个和后一个序列点之间,一个对象通过评估表达式最多只能修改其存储的值一次。
由于在两个连续的序列点之间只修改了一次i,因此出现了“获取失败”的情况。这就是为什么我们需要第二句话的原因。
这两个示例在C语言中都被禁止,因为访问了i的先前值两次,即i++本身在修改表达式时访问了i的先前值,因此无需访问i的先前值/值来确定要存储的修改值,因为它没有被访问到。

问题始于我提出的表达式i = i++,关于这一点在c-faq中有所说明。

实际上,我们讨论的其他表达式也违反了第二句话。

我认为在这个表达式中,i(在R.H.S中)被访问以确定i的修改值。
这个表达式如何违反第二个语句?

1个回答

2

这样来考虑:

a = i++;

等同于:

a = i;
i++;

访问增量中的i值与确定将存储到a的值无关。所以i=i++包含了对i的两次修改(这是第一句不允许的),但同时,对i++中对i的任一访问独立于对ii=修改。
我认为有人只是想过于聪明。没有必要去计算未定义行为的程度。对一个值进行两次修改足够产生未定义行为了。

好吧,严谨地说,它被访问了多少次是未定义的,因为整个表达式都是未定义的。 - Art

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接