最近几天,我一直在试图了解未定义行为。几天前,我找到了一个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 + 1
和a[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
的修改值。
这个表达式如何违反第二个语句?