2009-11-24 14 views
6

申し訳ありませんこれは単純ですが、私のC++は錆びています。ちょっと変わったC++コード

これは何をしていますか?私が見る限り、代入や関数呼び出しはありません。このコードパターンは、継承したいくつかのコードで何度も繰り返されます。それが重要であれば、それは埋め込まれたコードです。

*(volatile UINT16 *)&someVar->something; 

編集:そこから続き、次のコードでヒースズの疑惑を確認していますか? (正確にコードから、繰り返しを含め、名前が無実を保護するために変更されている以外)

if (!WaitForNotBusy(50)) 
    return ERROR_CODE_X; 

*(volatile UINT16 *)& someVar->something; 

if (!WaitForNotBusy(50)) 
    return ERROR_CODE_X; 

*(volatile UINT16 *)& someVar->something; 
x = SomeData; 
+1

埋め込みコード?次に、疑問に思ったように、これはおそらく物理的なアドレスです。 –

+0

注:私は以下の答えで記事へのリンクを追加しました:http://www.mjmwired.net/kernel/Documentation/volatile-considered-harmful.txt – Artyom

+0

読んだ結果をどこにもキャストすることをお勧めしますコンパイラの警告を避けるために、 '(void)'を使用してください。だから '(void)*(volatile uint16_t *)&someVar-> something'です。もちろん、これをマクロまたはインライン関数でラップして、カットアンドペーストしないでください! –

答えて

19

これは、デバイスレジスタにアクセスする必要がある組み込みプログラミング(関数やマクロのセットにカプセル化する必要があります)のかなり一般的なイディオムです。多くのアーキテクチャでは、デバイス・レジスタはメモリ・アドレスにマップされ、他の変数と同様にアクセスされます(ただし、固定アドレスでもポインタを使用できます。またはリンカまたはコンパイラ拡張でアドレスを固定できます)。しかし、Cコンパイラが変数アクセスに副作用を見ない場合、変数(または変数へのアクセスに使用されたポインタ)がvolatileとしてマークされていなければ、最適化できます。

です。

*(volatile UINT16 *)&someVar->something; 

は16ビットを発行するsomeVarポインタに格納されたアドレスから(something構造要素のオフセットによって提供される)オフセットいくつかを読み取ります。この読み取りは発生し、volatileキーワードのためにコンパイラによって最適化されません。

一部のデバイスレジスタは、読み込みが行われていても、読み取られたデータが他の方法で使用されない場合でも、一部の機能を実行します。これは、特定のビットのエラー状態を示すレジスタの読み出し後にエラー状態がクリアされる可能性があるステータスレジスタでは、非常に一般的です。

これはおそらくvolatileキーワードを使用するより一般的な理由の1つです。

+0

ありがとう、私はそれが最も明確で最も完全な応答だと思うので、これを答えとしてマークしました。 –

9

私は著者の意図は、コンパイラはこれらの点でメモリバリアを発光させることだったと思います。 volatileの式の結果を評価することにより、この式を最適化してはならず、各行の揮発性の場所へのアクセスの意味(メモリバリア、最適化の制限)を「インスタンス化」する必要がありますこのイディオムがどこにあるか。

このタイプのイディオムは、プリプロセッサマクロ(#define)に「カプセル化」することができます。これは、別のコンパイルで同じ効果を引き起こす別の方法がある場合です。たとえば、読み書きメモリバリアを直接エンコードできるコンパイラでは、このイディオムではなく組み込みのメカニズムを使用することがあります。このタイプのコードをマクロ内に実装することで、コードベース全体のメソッドを変更することができます。

EDIT:ユーザーsharthこのコードは、ポインタのアドレスが物理なく仮想アドレス(または特定の物理アドレスにマッピングされた仮想アドレス)である環境で実行された場合、その優れた点を有し、この読み取り操作を実行すると、周辺機器で何らかのアクションが発生する可能性があります。

+2

さらに、マクロは何が起こっているのかをより明確にすることができます。(#define READ_MEMORY_BARRIER ...) – Aaron

+1

最初のステップは、実際にメモリバリアを作成するかどうかを評価することです。これは意図のようですが、多くのプラットフォーム上の揮発性変数は、他の揮発性変数に関してのみ順序付けられます。この組み込みプラットフォームで動作しても、別のプラットフォームでは動作しない可能性があります。私は障壁を作成するためのより良い、よりポータブルなソリューションを探しています。 –

+1

私はメモリの壁とは何の関係もありません。組み込みプラットフォームであり、おそらく変数をIOにマップします。 –

9

ここでは長いショットです。

このアドレスがFPGAまたは他のデバイス上のメモリマップ領域を指している場合、そのアドレスを読み取ったときに実際にデバイスが動作している可能性があります。

+0

なぜロングショット?私はそれが完全に論理的な説明だと思う。 +1 –

+0

元の質問には、組み込みシステムなどでこれが起こっていることを明確にする明確な説明がありませんでした。 –

-1

これは一般的に悪いコードです。

揮発性とは、揮発性が非常に低く、暗黙のメモリバリアを提供しないことを意味します。だから、このコードはちょうどかなり間違っていると書いてあります。

memory_barrier(); 
*(volatile UINT16 *)&someVar->something; 

これは単なる悪いコードです。

エクスパンデーション:volatile可変原子を作成しません!

リードこの記事:http://www.mjmwired.net/kernel/Documentation/volatile-considered-harmful.txt

volatileが適切なコードで使用しないことがほとんどない必要がある理由です。

+2

Eh !?どういう意味ですか? – Clifford