编译器可能不会跨序列点移动对volatile变量的访问;这是什么意思?

将变量声明为“volatile”意味着直接从内存位置读取/写入,而不是从寄存器变量读取/写入.我对’序列点’有所了解.但我不明白标题中提到的陈述.

有人可以解释一下,并给出一些代码片段吗?

所有这些都在C11 5.1.2.3中描述

Program execution

/–/

Accessing a volatile object, modifying an object, modifying a file, or calling a function
that does any of those operations are all side effects, which are changes in the state of
the execution environment. Evaluation of an expression in general includes both value
computations and initiation of side effects.

Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations
executed by a single thread, which induces a partial order among those evaluations.
Given any two evaluations A and B, if A is sequenced before B, then the execution of A
shall precede the execution of B.

The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B.

/–/

An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced (including any caused by calling a function or accessing a volatile object).

/–/

The least requirements on a conforming implementation are:

— Accesses to volatile objects are evaluated strictly according to the rules of the abstract
machine.

这不是很容易理解,但它在简单的英语中大致意味着:因为易失性对象的访问是副作用,所以不允许编译器优化这些访问,也不允许它们在不同的顺序,否则它可能会在具有指令缓存/分支预测的CPU上获得更好的性能,或者只是更好的性能,因为它具有方便地存储在某些CPU寄存器中的某些值.

(C11标准还明确声明不保证volatile对象是线程安全的,上下文切换后volatile对象的值是未指定的行为.)

编辑一个例子

鉴于代码

volatile int x;
volatile int y;
volatile int z;

x=i;
y=something;
z=i;

那么编译器不允许重新排序可执行文件中的指令

x=i;
z=i;
y=something

因为必须在访问z之前对y的访问进行排序.半结肠有一个序列点.但是如果变量不是易变的,那么编译器可以重新排序它们,如果它可以确定它不会影响程序的结果.

相关文章
相关标签/搜索