2012-03-29 7 views
57

volatileは、すべての読み取り/書き込みがレジスタに格納された値を使用せずに実際のメモリアクセスを行うように、参照を最適化しないようにコンパイラに指示することです。私はそれがいくつかの普通の変数にとっては有益だと理解できますが、どのようにポインタに影響するのか理解していません。volatile"volatile int * p"のようなpoint-to-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と宣言されている場合の相違点は何ですか?

答えて

101

形態

volatile int* p; 

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

volatile int*のための1つ以上のユースケースがあります:あなたはvolatileとしてintを宣言する場合は、通常のint*でそれを指してはいけません。たとえば、これは悪い考えです:

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

この理由は、Cコンパイラは、もはや変数がptrvolatileあるが指すことを覚えて、それが間違ってレジスタに*pの値をキャッシュするかもしれないということではありません。実際、C++では、上記のコードはエラーです。代わりに、あなたは

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

さて、コンパイラはvolatile intptrそのポイントを覚えているので、それはないでしょう書くべき(またはすべきでない!)を最適化しよう*ptrを通じてアクセスします。

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

int* volatile ptr; 

をこれは、ポインタ自体ポインタ自体は、コンパイラは、メモリ内のポインタをキャッシュするか、ポインタ値を最適化しようと試みるべきではないことを意味し、volatileであると述べています

volatile int* volatile ptr; 

これは、ポインタと指示先の両方が予期せず変更を取得できることを述べている:あなたはこの獣を取得したい場合あなたが一緒にこれらを組み合わせることができます何か他のもの(ハードウェア、別のスレッドなど)によって再割り当てされる可能性があります。コンパイラはポインタ自体を最適化することはできず、指されているものを最適化することはできません。

希望すると便利です。

+0

私はあなたが "あなたはそれを定期的なint *で指してはいけない"と思うと思います。 – markgz

+0

@ markgz-おっと!それは正解です。一定。 – templatetypedef

+0

私はC言語でもエラーだと思いますが、Cコンパイラは型の不一致について不平を言うことは少なくありません。 –

6

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

あなたは揮発性だけでなく、int型であることを、ポインタを必要万一、あなたが使用する必要がありますが:

volatile int * volatile p; 

私はあなたがそれを使用する必要があり、状況を考えることはできません。

+2

例:Iポインタとそれが指しているデータを変更するISRコードで、volatile volatile uint8_t * volatile pDataを使用しています。ポインタはメインコードによって設定され、ポインタとデータは後で読み込まれます。 – Christoph

関連する問題