volatile
は、参照を最適化しないようにコンパイラーに指示し、すべての読み取り/書き込みがレジスターに格納された値を使用せず、実際のメモリーアクセスを行うようにします。私はそれが普通の変数に役立つことは理解できますが、volatile
がポインターにどのように影響するかを理解していません。
volatile int *p = some_addr;
int a = *p; // CPU always has to load the address, then does a memory access anyway, right?
int *p = some_addr
として宣言されている場合の違いは何ですか?
フォームのポインター
volatile int* p;
コンパイラがint
として扱うvolatile
へのポインタです。これは、ソースコードにこれが発生する可能性があることを示唆するものがない場合でも、p
が指している変数が変更されている可能性があるとコンパイラが想定することを意味します。たとえば、p
が通常の整数を指すように設定すると、*p
を読み書きするたびに、コンパイラは値が予期せず変更された可能性があることを認識します。
volatile int*
にはもう1つの使用例があります。int
をvolatile
として宣言する場合、通常のint*
でそれを指すべきではありません。たとえば、これは悪い考えです。
volatile int myVolatileInt;
int* ptr = &myVolatileInt; // Bad idea!
これは、Cコンパイラがptr
が指す変数がvolatile
であることを覚えていないため、*p
の値をレジスタに誤ってキャッシュする可能性があるためです。実際、C++では、上記のコードはエラーです。代わりに、書く必要があります
volatile int myVolatileInt;
volatile int* ptr = &myVolatileInt; // Much better!
現在、コンパイラはptr
がvolatile int
を指していることを記憶しているため、*ptr
を介してアクセスを最適化しようとしません(またはすべきではありません!)。
最後の詳細-議論したポインターは、volatile int
へのポインターです。これも行うことができます:
int* volatile ptr;
これは、ポインターitselfがvolatile
であると言います。つまり、ポインター自体が再割り当てされる可能性があるため、コンパイラーはポインターをメモリーにキャッシュしたり、ポインター値を最適化しようとするべきではありません他の何か(ハードウェアなど)で、この獣を手に入れたい場合は、これらを組み合わせることができます。
volatile int* volatile ptr;
これは、ポインタと指示先の両方が予期せず変更される可能性があることを示しています。コンパイラーは、ポインター自体を最適化することはできず、ポイントされているものを最適化することもできません。
お役に立てれば!
このコードvolatile int *p = some_addr
は、volatile int
へのポインターを宣言します。ポインター自体はvolatile
ではありません。
ポインタが揮発性であるだけでなくintである必要があるというまれなイベントでは、次を使用する必要があります。
volatile int * volatile p;
あなたがそれを使う必要がある状況は考えられません。
Volatileの有用性:シリアルインターフェイスコントローラーのようなハードウェアによって変更されるメモリをチェックする必要がある場合、これが必要です。 OSを介さずにハードウェアに非常に近い場所で作業する組み込みシステムの世界にそのアプリケーションがあります。