多くの低レベルのプログラムは、しかし、私は一種のそれは何にとして困惑している、メモリマッピングなどのための種類の揮発性のキーワードを使用REALLYバックグラウンドで行います。つまり、コンパイラがメモリアドレスを「最適化しない」とはどういう意味ですか?
多くの低レベルのプログラムは、しかし、私は一種のそれは何にとして困惑している、メモリマッピングなどのための種類の揮発性のキーワードを使用REALLYバックグラウンドで行います。つまり、コンパイラがメモリアドレスを「最適化しない」とはどういう意味ですか?
回答:
volatile
他の何らかのプロセッサやI / Oデバイス、あるいは何かがあなたの下から変数を変更できることを意味します。
通常の変数では、プログラムのステップがそれを変更する唯一のものです。したがって、たとえば5
、変数から読み取り、それを変更しない場合でも、変数にはが含まれます5
。これを信頼できるので、次に変数を使用するときに、プログラムで時間をかけて変数を再度読み取る必要はありません。C ++コンパイラは、を記憶するだけのコードを生成するのに優れています5
。
しかし5
、それをとして読み取ると、おそらくシステムがディスクからそのメモリにデータをロードし、に変更し500
ます。プログラムに新しい値を読み取らせる500
場合は、コンパイラーが以前に読み取った値を使いすぎないようにする必要があります5
。毎回値をリロードするように指示する必要があります。それが何をするかvolatile
です。
5歳児の例え
大きな紙をテーブルに置いたとします。紙の片隅に、進行中のゲームの現在のスコアを書き留めます3 to 4
。次に、テーブルの反対側に行き、ゲームについてのストーリーを書き始めます。ゲームを見ている友達は、ゲームが進むにつれてそのコーナーのスコアを更新します。彼女は消し3 to 4
書きします3 to 5
。
ゲームのスコアをストーリーに追加するときは、次のいずれかを行うことができます。
3 to 4
。楽にそれが変化しなかった(または変化したかどうか気にしない)と仮定します、または3 to 5
歩き回り、現在のスコア(たまたま現在のスコア)を読み、戻ってください。これがvolatile
変数の動作方法です。volatile
2つのことを意味します。
変数の値は、コードを変更しなくても変更される場合があります。コンパイラは変数の値を読み取るしたがってたびに、それができるではない、それが読み込まれた前回と同じである、またはそれが格納された最後の値と同じであるが、それは再び読み出されなければならないことを仮定する。
揮発性変数に値を格納する動作は、外部から観察できる「副作用」であるため、コンパイラは値を格納する動作を削除できません。たとえば、2つの値が連続して格納される場合、コンパイラは実際に値を2回格納する必要があります。
例として:
i = 2;
i = i;
コンパイラーは、数値2を保管し、変数iを読み取り、読み取った変数をiに保管する必要があります。
別の状況もあります。関数が使用setjmp
してからlongjmp
呼び出された場合、関数のすべての揮発性ローカル変数には、最後の値が格納されることが保証されます。これは、不揮発性ローカル変数の場合とは異なります。
i
pi = &i
x = *pi
i
i
として宣言されvolatile int i
た後pi
のように宣言する必要がありvolatile int *pi
、その場合には、*pi
いや、揮発性のアクセスですか?
抽象説明
CもC ++も抽象マシンの概念を持っています。コードがある変数の値を使用する場合、抽象マシンは実装がその変数の値にアクセスする必要があると言います。フォームのコードは、statement_A; statement_B; statement_C;
指定された順序どおりに実行する必要があります。これら3つのステートメントに共通する式は、出現するたびに再計算する必要があります。
抽象マシンごとに、ステートメントのシーケンスが与えられた場合statement_A; statement_B; statement_C;
、実装は最初にstatement_A
全体を実行し、次にを実行し、statement_B
最後にを 実行する必要がありstatement_C
ます。実装ではage
、値5 を割り当てたことを思い出せません。参照するすべてのステートメントは、age
代わりにその変数の値にアクセスする必要があります。
volatile
実装が抽象マシン仕様に従ってCまたはC ++コードを厳密に実行する場合、キーワードは必要ありません。CおよびC ++の抽象マシンには、レジスタの概念、共通の副次式の概念はなく、実行順序は厳密です。
どちらの言語にもas-ifルールがあります。実装は、抽象マシン仕様に従って実行したかのように動作する限り、標準に準拠しています。コンパイラーは、不揮発性変数が割り当て間で値を変更しないと想定できます。as-if
ルールに違反しない限り、シーケンスstatement_A; statement_B; statement_C;
はstatement_C
、の一部、次にの一部statement_A
、次にのすべてstatement_B
、残りのstatement_A
、最後にの残りを実行することで実装できますstatement_C
。
これらのas-ifルールはvolatile
変数には適用されません。volatile
変数と関数に関しては、実装は、実行するように指示したとおりに、実行するように指示したとおりに実行する必要があります。
抽象マシン仕様には欠点があります。遅いです。他の言語と比較したCおよびC ++の良い点の1つは、非常に高速であることです。これは、これらの抽象マシンごとにコードが実行された場合には当てはまりません。AS-場合のルールはCとC ++は非常に高速であることを可能にするものです。
ELI5回答
コンパイラがメモリアドレスを「最適化しない」とはどういう意味ですか?
メモリアドレスを「最適化」することは高度な概念であり、5歳児の能力の範囲に含まれないものです。従順な5歳児は、あなたが言うように、それ以上、それ以下ではありません。を使用volatile
すると、実装は5のように動作するように指示されます。代わりに、実装は、コードが指示するとおりに実行する必要があります。
答えはかなり一貫しているように見えますが、重要なポイントがありません。スペースを割り当て、すべてのアクセス(読み取りまたは書き込み)に対して、そのアクセスを実行するようコンパイラーに指示しています。何らかの理由でそれらのアクセスまたはその変数を最適化することを望まない。
はい、1つの理由は、他の誰かが私たちのためにその値を変更する可能性があるためです。別の理由は、他の誰かのためにその値を変更する可能性があることです。他の誰かが私たちのためにそれを変更するのか、私たちがそれを変更するのかは、ハードウェア/ロジックまたはソフトウェアかもしれません。これは、ハードウェアへの書き込みまたはハードウェアからの読み取りを行う、ベアメタル組み込みプログラムの制御およびステータスレジスタへのアクセスを定義するためによく使用されます。他の答えで説明されているソフトウェアと話すソフトウェアと同様に。
コードのセクションの時間を計ろうとしている場合に、アクセスが発生するタイミングと順序を制御するためにvolatileが使用されていることもわかります。また、volatileを使用しない場合は、問題の変数(開始時刻、終了時刻、差分)のみを使用する必要があります。終わり近くに計算されたコンパイラーは、時間測定値のいずれかを(私たちが配置した場所ではなく)自由に移動できます。
時々、それは単に時間を燃やすために使用されるのを見るでしょう、エレメンタリーLEDウィンカー、ベアメタルのHello Worldは、人間の目がLEDを見るのに時間を費やすためだけに数に数える変数に揮発性を使用するかもしれません状態を変更します。タイマーやその他のイベントを使用して時間を消費する、より高度な例。
volatile
、変数と、それは5を言うと、あなたが来年再びそれを読んで、あなたは6取得することが保証している