问题描述
微控制器通常需要读取寄存器才能清除某些状态。在C中是否有便携式方法,以确保如果不使用数据,则读取不会被优化?指向内存映射寄存器的指针是否被声明为volatile?换句话说,以下是否符合标准的编译器? void func(void)
{
volatile unsigned int * REGISTER =(volatile unsigned int *)0x12345678;
* REGISTER;
}
People argue quite strenuously about exactly what volatile
means. I think most people agree that the construct you show was intended to do what you want, but there is no general agreement that the language in the C standard actually guarantees it as of C99. (The situation may have been improved in C2011; I haven't read that yet.)
A nonstandard, but fairly widely supported by embedded compilers, alternative that may be more likely to work is
void func(void)
{
asm volatile ("" : : "r" (*(unsigned int *)0x12345678));
}
(The 'volatile' here appies to the 'asm' and means 'this may not be deleted even though it has no output operands. It is not necessary to put it on the pointer as well.)
The major remaining drawback of this construct is that you still have no guarantee that the compiler will generate a one-instruction memory read. With C2011, using _Atomic unsigned int
might be sufficient, but in the absence of that feature, you pretty much have to write a real (nonempty) assembly insert yourself if you need that guarantee.
EDIT: Another wrinkle occurred to me this morning. If reading from the memory location has the side-effect of changing the value at that memory location, you need
void func(void)
{
unsigned int *ptr = (unsigned int *)0x12345678;
asm volatile ("" : "=m" (*ptr) : "r" (*ptr));
}
to prevent mis-optimization of other reads from that location. (To be 100% clear, this change will not change the assembly language generated for func
itself, but may affect optimization of surrounding code, particularly if func
is inlined.)
这篇关于如何强制C中未使用的内存读取不会被优化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!