register キーワードは値を計算するためのレジスタを割り当て、volatile キーワードは変数に対して何らかの計算を実行し、基本的にコードを最適化しないたびにメモリから値を読み取ることを理解しています。したがって、変数にこれらの両方のキーワードが割り当てられている場合、それは本質的にそれ自体が揮発性であることを意味しますか? サンプルコードを書いても挙動が分かりません。誰か光を当てることができますか?
2 に答える
C では、register
ストレージ クラスはストレージ クラスとまったく同じように動作しますauto
が、プログラムがオブジェクトのアドレス (6.5.3.2、6.7.1 )。コンパイラへの最適化のヒントとして を使用することはregister
、一般に無意味です。コンパイラは、オブジェクトの非格納品質を利用するのに十分賢いので、どのオブジェクトを宣言できるかを追跡するのに十分賢いからregister
です。代わりに、プログラマーがオブジェクトのアドレスを取得することによって最適化の機会をうっかり破壊していないことをコード品質チェックとして理解する必要があります。
register
つまり、有効なプログラムからキーワードのすべてのインスタンスを削除しても、プログラムのセマンティクスには影響しません。この点では に似ていstatic_assert
ます。
型修飾子は、オブジェクトへのvolatile
アクセス (読み取りと書き込み) が副作用と見なされ、最適化して取り除くことができないことを示します。register
定義されたロケーション メモリ (つまり、ストレージ クラスを持つオブジェクト) に存在しないオブジェクトの場合、これはパフォーマンス テストで最も役立ちます。
start = time();
for (multiple loops)
register volatile int result = test_function();
stop = time();
elapsed = stop - start;
volatile
オブジェクトがコンパイラにとって予測できない方法で変更される可能性がありregister
、そのアドレスを取得できないことを意味します。
オブジェクトが実際にはプラットフォーム上のハードウェアレジスタである場合、両方の組み合わせは完全に理にかなっています。一部のコンパイラ (gcc など) には、このような変数を特定のハードウェア レジスタに固定するための拡張機能もあります。
他のコードがそのようなハードウェア レジスタを変更する可能性があるため、コンパイラは現在の値について何も想定しない場合があります。そのような場合、const
修飾子を追加することも理にかなっています。たとえば、gcc の拡張機能を使用した場合
register uint32_t volatile const eax __asm__("eax");
eax
いつでもレジスタを検査できるツールがあればよいのですが、誤ってレジスタを変更することはできません。