考虑以下代码示例:
int main(void)
{
volatile int a;
static volatile int b;
volatile int c;
c = 20;
static volatile int d;
d = 30;
volatile int e = 40;
static volatile int f = 50;
return 0;
}
如果没有 volatile
,编译器可以优化掉所有变量,因为它们永远不会被读取 .
我认为 a
和 b
可以被优化掉,因为它们完全未使用,请参阅unused volatile variable .
我认为 c
和 d
无法被删除,因为它们被写入,并且必须实际发生对volatile变量的写入 . e
应相当于 c
.
GCC不会优化 f
,但它也不会发出任何写入指令 . 在数据部分中设置50 . LLVM(clang)完全删除 f
.
这些陈述是真的吗?
-
如果永远不会访问volatile变量,则可以对其进行优化 .
-
静态或全局变量的初始化不计为访问 .
2 回答
写入volatile变量(甚至是自动变量)算作可观察行为 .
C11(N1570)5.1.2.3/6:
问题是:初始化(
e
,f
)算作"access"吗?正如Sander de Dycker所指出的那样,6.7.3说:这意味着由编译器决定是否可以优化
e
和f
- 但这必须记录在案!严格地说,根据C标准,无法优化访问(读取或写入)的任何易失性变量 . 标准说,访问易失性对象可能具有未知的副作用,并且对volatile对象的访问必须遵循C抽象机器的规则(其中所有表达式按其语义指定进行评估) .
从强大的标准(强调我的):
接下来,即使简单的变量初始化也应被视为访问 . 请记住
static
说明符也会导致对象被初始化(到0
)并因此被访问 .现在已知编译器对volatile限定符的行为有所不同,我猜他们中的很多只会优化示例程序的大多数volatile对象,除了那些具有显式赋值(
=
)的对象 .