为什么“volatileQualifiedExpr + volatileQualifiedExpr”不一定是C中的UB而是C ++中的UB?

当我今天阅读C标准时,它说的是副作用

访问易失性对象,修改对象,修改文件或调用执行任何这些操作的函数都是副作用

和C ++标准说

访问由volatile glvalue(3.10)指定的对象,修改对象,调用库I / O函数或调用执行任何这些操作的函数都是副作用

因此,因为禁止在同一个标​​量对象上发生无序的副作用,C允许以下内容,但C ++使其成为未定义的行为

int a = 0; volatile int *pa = &a; int b = *pa + *pa; 

我正确地阅读了规格吗? 如果出现差异,原因是什么?

我不相信在这方面C和C ++之间存在有效的变化。 尽管关于排序的措辞有所不同,但最终结果是相同的:两者都会导致未定义的行为(尽管C似乎表明评估将取得成功,但结果不明确)。

在C99(抱歉,没有C11方便)第5.1.2.3.5段规定:

– 在序列点处,易失性对象在先前访问完成且后续访问尚未发生的意义上是稳定的。

结合5.1.2.3.2的引用,表明对于至少一次访问papa的值不会处于稳定状态。 这具有逻辑意义,因为允许编译器以任何顺序,仅一次或同时(如果可能)对它们进行评估。 然而,它实际上并没有定义稳定的意思。

在C ++ 11中,明确提到了1.9.13处的未测序事件。 然后,点15表示对同一操作数的这种未序列操作是未定义的。 由于未定义的行为可能意味着任何事情发生,它可能比C的不稳定行为强。 但是,在这两种情况下都没有保证表达的结果。