人们非常激烈地争论到底是什么volatile
意思。我认为大多数人都同意您展示的构造旨在执行您想要的操作,但是对于 C 标准中的语言实际上在 C99 中保证它并没有普遍的共识。(情况可能在 C2011 有所改善;我还没有读到。)
一种非标准的但被嵌入式编译器广泛支持的替代方案可能更有可能工作是
void func(void)
{
asm volatile ("" : : "r" (*(unsigned int *)0x12345678));
}
(这里的“volatile”适用于“asm”,意思是“即使它没有输出操作数,也不能删除它。也不必将它放在指针上。)
这种结构的主要缺点是您仍然无法保证编译器将生成单指令内存读取。使用 C2011,使用_Atomic unsigned int
可能就足够了,但是在没有该功能的情况下,如果您需要该保证,您几乎必须自己编写一个真实的(非空)程序集插入。
编辑:今天早上我又出现了一个皱纹。如果从内存位置读取具有更改该内存位置值的副作用,则需要
void func(void)
{
unsigned int *ptr = (unsigned int *)0x12345678;
asm volatile ("" : "=m" (*ptr) : "r" (*ptr));
}
以防止对该位置的其他读取进行错误优化。(要 100% 清楚,此更改不会更改为func
自身生成的汇编语言,但可能会影响周围代码的优化,尤其func
是内联代码时。)