volatile修飾子をつけて変数宣言すると,その変数は最適化の対象から外され,レジスタに割り付ける最適化などを行わなくなります。volatile指定された変数に対する操作を行うときは,必ずメモリから値を読み込み,操作後にメモリへ値を書き込むコードになります。また,volatile指定された変数のアクセス幅も変更されません。
volatile指定されていない変数は,最適化によってレジスタに割り付けられ,その変数をメモリからロードするコードが削除されることがあります。また,volatile指定されていない変数に同じ値を代入する場合,冗長な命令と解釈されて最適化により命令が削除されることもあります。特に周辺I/Oレジスタへアクセスする変数や,割り込み処理で値が変更される変数,また,外部から値が変更される変数に対しては,volatile指定する必要があります。
volatile指定すべきところで指定されていなかった場合,次の現象が起こることがあります。
ただし,volatile指定した変数を使用する際,ある区間でその変数の値が外部から変更されないことが自明な場合,volatile指定されていない変数に,その値を代入してその変数を参照することにより,その変数が最適化され,実行速度が向上する可能性があります。
【volatile指定しなかった場合のソースと出力コードの例】
“変数a”,“変数b”,および“変数c”をvolatile指定しなかった場合,これらの変数がレジスタに割り付けられ,最適化されます。たとえば,この間に割り込みが入り,割り込み内で変数値を変更しても,値が反映されないことになります。
“変数a”,“変数b”,および“変数c”をvolatile指定した場合,これらの変数値を必ずメモリから読み込み,操作後にメモリへ書き込むコードが出力されます。たとえば,この間に割り込みが入り,割り込み内で変数値が変更されても,その変更が反映された結果を取得することができます(このような例の場合,割り込みのタイミングによっては,変数の操作区間内を割り込み禁止にするなどの処置が必要となります)。
volatile指定をすると,メモリの読み込み/書き込み処理が入るため,volatile指定しなかった場合よりもコード・サイズは大きくなります。