11

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

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

和 C++ 标准说

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

因此,因为两者都禁止在同一个标​​量对象上发生未排序的副作用,所以 C 允许以下情况,但 C++ 使其成为未定义的行为

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

int b = *pa + *pa;

我是否正确阅读规范?如果是这样,差异的原因是什么?

4

1 回答 1

1

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

在 C99 中(对不起,手边没有 C11)第 5.1.2.3.5 段指定:

— 在序列点,易失性对象是稳定的,因为先前的访问已完成,而后续的访问尚未发生。

结合您从 5.1.2.3.2 中引用的内容,将表明 的值pa对于至少其中一次访问pa. 这是合乎逻辑的,因为编译器将被允许以任何顺序评估它们,一次或同时(如果可能的话)。然而,它实际上并没有定义稳定的含义。

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

于 2012-10-14T15:03:12.650 回答