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

Why is "volatileQualifiedExpr + volatileQualifiedExpr" not necessarily UB in C but in C++?

本文关键字:UB 中的 volatileQualifiedExpr 而是 C++ 不一定 为什么      更新时间:2023-10-16

当我今天阅读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段规定:

在序列点,volatile对象是稳定的,因为以前的访问是完整的和后续的访问尚未发生。

与5.1.2.3.2中的报价相结合将表明pa的值在至少一次访问pa时不会处于稳定状态。这在逻辑上是有意义的,因为编译器可以按任何顺序对它们求值,只需一次或同时(如果可能的话)。然而,它实际上并没有定义稳定的含义。

在C++11中,在1.9.13中明确引用了未排序的操作。则点15指示对同一操作数的这种未排序操作是未定义的。由于未定义的行为可以意味着发生任何事情,它可能比C的不稳定行为更强。然而,在这两种情况下,都不能保证你的表达结果。