web-dev-qa-db-ja.com

「volatile int * p」のようなポイントツーボラティリティポインタが役立つのはなぜですか?

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として宣言されている場合の違いは何ですか?

69
Infinite

フォームのポインター

volatile int* p;

コンパイラがintとして扱うvolatileへのポインタです。これは、ソースコードにこれが発生する可能性があることを示唆するものがない場合でも、pが指している変数が変更されている可能性があるとコンパイラが想定することを意味します。たとえば、pが通常の整数を指すように設定すると、*pを読み書きするたびに、コンパイラは値が予期せず変更された可能性があることを認識します。

volatile int*にはもう1つの使用例があります。intvolatileとして宣言する場合、通常のint*でそれを指すべきではありません。たとえば、これは悪い考えです。

volatile int myVolatileInt;
int* ptr = &myVolatileInt; // Bad idea!

これは、Cコンパイラがptrが指す変数がvolatileであることを覚えていないため、*pの値をレジスタに誤ってキャッシュする可能性があるためです。実際、C++では、上記のコードはエラーです。代わりに、書く必要があります

volatile int myVolatileInt;
volatile int* ptr = &myVolatileInt; // Much better!

現在、コンパイラはptrvolatile intを指していることを記憶しているため、*ptrを介してアクセスを最適化しようとしません(またはすべきではありません!)。

最後の詳細-議論したポインターは、volatile intへのポインターです。これも行うことができます:

int* volatile ptr;

これは、ポインターitselfvolatileであると言います。つまり、ポインター自体が再割り当てされる可能性があるため、コンパイラーはポインターをメモリーにキャッシュしたり、ポインター値を最適化しようとするべきではありません他の何か(ハードウェアなど)で、この獣を手に入れたい場合は、これらを組み合わせることができます。

volatile int* volatile ptr;

これは、ポインタと指示先の両方が予期せず変更される可能性があることを示しています。コンパイラーは、ポインター自体を最適化することはできず、ポイントされているものを最適化することもできません。

お役に立てれば!

128
templatetypedef

このコードvolatile int *p = some_addrは、volatile intへのポインターを宣言します。ポインター自体はvolatileではありません。

ポインタが揮発性であるだけでなくintである必要があるというまれなイベントでは、次を使用する必要があります。

volatile int * volatile p;

あなたがそれを使う必要がある状況は考えられません。

9
markgz

Volatileの有用性:シリアルインターフェイスコントローラーのようなハードウェアによって変更されるメモリをチェックする必要がある場合、これが必要です。 OSを介さずにハードウェアに非常に近い場所で作業する組み込みシステムの世界にそのアプリケーションがあります。

1
sdiedrichsen