適用範囲:DS-5, RealView Development Suite (RVDS), ARM Developer Suite (ADS)
以下のような問題が発生する場合:
- メモリマップされたハードウェアへの読み書きの問題
- ハードウェアのポーリング時に、ループから動かなくなる
- スレッド化プログラムでおかしな振舞いをする 上記のような問題が特に高度な最適化レベル(-O2および-O3)で見られるが、低い最適化レベルでは発生しない場合、一部の変数をvolatileとして定義する必要がある事があります。
変数がvolatileとして宣言されると、コンパイラはそのオブジェクトはコードで見える範囲外から変更される可能性があると仮定します。
これは、メモリアクセスを避けるためにコンパイラが変数をローカルレジスタへ割り当てる動作を含んだ多くの最適化を行わないことを示します。
変数がvolatileなしで宣言されると、値は外部から変えられることがないと想定し、多くの最適化が適用されます。
変数をvolatileと宣言する必要があるとおもわれるのには数多くの異なった状況があります。以下を含みます:
- メモリマップされたペリフェラルへのアクセス
- 複数のスレッド間で共有される変数
- 割り込みルーチン内でアクセスされるグローバル変数
以下の簡単なサンプルはグローバル変数をvolatileとして宣言したときのコード生成に対する影響を示します
Cコード:
/* volatile */ int buffer_full; void read_stream(void) { int count; while (!buffer_full) { count++; } }
buffer_fullをvolatileとして宣言しなかった場合のコード生成:
LDR r0,[pc,#12] ; Load address of "buffer_full" LDR r0,[r0,#0] ; Load "buffer_full" loop CMP r0,#0 ; Check "buffer_full" BEQ loop ; If not "buffer_full" branch to loop --> code stuck in loop!
buffer_fullをvolatileとして宣言た場合のコード生成:
LDR r1,[pc,#12] ; Load address of "buffer_full" loop LDR r0,[r1,#0] ; Load "buffer_full" CMP r0,#0 ; Check "buffer_full" BEQ loop ; If not "buffer_full" branch to loop
count++はプログラムに影響を与えないため最適化されていることに注意してください。