時間の関係で、volatileキーワードはまだ要約されていないので、その後の忘れを防ぐために、いくつかの良い要約ブログを投稿します。
volatileキーワードは、次の状況で必要です。
1.並列デバイスのハードウェアレジスタ(ステータスレジスタなど)
メモリマップドハードウェアレジスタは、通常、ボリュームを追加する必要があります。これは、レジスタへの読み取りと書き込みがそれぞれ異なる意味を持つ可能性があるためです。
#define GPC1CON *((volatile unsigned int *)0xE0200080)
#define GPC1DAT *((volatile unsigned int *)0xE0200084)
#define GPC1PUD *((volatile unsigned int *)0xE0200088)
2.割り込みサービスサブルーチンでアクセスされる非自動変数(非自動変数)
レジスタへのアクセス速度はRAMの速度よりも速いため、コンパイラは通常、外部RAMへのアクセスを減らすために最適化を行います。次に例を示します。
static int i=0; //i 为非自动变量
int main(void)
{
...
while (1){
//由于编译器判断在 main 函数里面没有修改过 i,因此可能只执行一次对从i到某寄存器的读操作,
//然后每次if判断都只使用这个寄存器里面的“i副本”,导致 dosomething 永远也不会被调用。
if (i) dosomething();
}
}
/* Interrupt service routine. */
void ISR_2(void)
{
i=1;
}
3.マルチスレッドアプリケーションの複数のタスクで共有される変数
2つのスレッドが特定の変数を使用する必要があり、変数の値が変更される場合は、その変数をvolatileで宣言する必要があります。このキーワードの機能は、最適化コンパイラが変数をメモリからCPUレジスタにロードしないようにすることです。変数がレジスタにロードされると、2つのスレッドがメモリ内の変数を使用し、もう1つがレジスタ内で変数を使用する可能性があります。これにより、プログラムが誤って実行されます。揮発性とは、コンパイラが既存のレジスタの値を使用するのではなく、変数を操作するたびに実際にメモリから変数をフェッチする必要があることを意味します。
volatile BOOL bStop = FALSE; //bStop 为共享全局变量
(1) 在一个线程中:
while( !bStop ) { ... }
bStop = FALSE;
return;
(2) 在另外一个线程中,要终止上面的线程循环:
bStop = TRUE;
while( bStop );
上記のスレッドが終了するのを待ちます。bStopがvolatile宣言を使用しない場合、bStopがレジスタに読み込まれているため、このループは無限ループになります。レジスタ内のbStopの値がFALSEになり、さらにvolatileになることはありません。プログラムが実行されているbStopの値が毎回メモリから読み取られる場合、無限ループは発生しません。