人々は、正確に何volatile
を意味するのかについて非常に熱心に議論しています。ほとんどの人は、あなたが示す構成があなたが望むことをすることを意図していたことに同意すると思いますが、C標準の言語がC99の時点で実際にそれを保証するという一般的な合意はありません。(C2011では状況が改善された可能性があります。まだ読んでいません。)
非標準ですが、組み込みコンパイラによってかなり広くサポートされており、動作する可能性が高い代替手段は次のとおりです。
void func(void)
{
asm volatile ("" : : "r" (*(unsigned int *)0x12345678));
}
(ここでの「volatile」は「asm」に適用され、「これは出力オペランドがなくても削除されない可能性があることを意味します。ポインターにも置く必要はありません。)
この構成の主な残りの欠点は、コンパイラが1命令のメモリ読み取りを生成するという保証がまだないことです。C2011では、を使用するだけで十分_Atomic unsigned int
かもしれませんが、その機能がない場合は、保証が必要な場合は、実際の(空でない)アセンブリインサートを自分で作成する必要があります。
編集:今朝私に別のしわが発生しました。メモリ位置からの読み取りに、そのメモリ位置の値を変更するという副作用がある場合は、次のようにする必要があります。
void func(void)
{
unsigned int *ptr = (unsigned int *)0x12345678;
asm volatile ("" : "=m" (*ptr) : "r" (*ptr));
}
その場所からの他の読み取りの誤最適化を防ぐため。func
(100%明確にするために、この変更はそれ自体のために生成されたアセンブリ言語を変更しませんが、特にfunc
インラインの場合、周囲のコードの最適化に影響を与える可能性があります。)