C の連結リストの次のフィールドの最下位ビットに関する次のステートメントを見つけました。
「C では、次のフィールドはポインタです。プロセッサのメモリ サブシステムに関連するパフォーマンス上の理由から、メモリはワード境界に割り当てられ、(少なくとも) 次のポインタの 2 つの最下位ビットは 0 です。」
これは本当ですか?もしそうなら、なぜそうなのか理解できません。助けてください。
C の連結リストの次のフィールドの最下位ビットに関する次のステートメントを見つけました。
「C では、次のフィールドはポインタです。プロセッサのメモリ サブシステムに関連するパフォーマンス上の理由から、メモリはワード境界に割り当てられ、(少なくとも) 次のポインタの 2 つの最下位ビットは 0 です。」
これは本当ですか?もしそうなら、なぜそうなのか理解できません。助けてください。
多くのプロセッサ アーキテクチャは、操作がワード アラインされたアドレスで実行されるように設計されています。たとえば、一部の 32 ビット プロセッサは、アドレス 0、4、8、12、16、20 などの 4 バイト (32 ビット) の倍数であるアドレスでワード演算を実行する必要があるように設計されています。同様に、一部の 64 ビット プロセッサでは、8 バイトの倍数のアドレスでのみワード操作を実行できます。これには、2 つの異なる命令がメモリ内の同じワードを参照しているかどうかをより簡単に検出できるなど、ハードウェアにさまざまな利点があり、プロセッサが高速になります。一部のプロセッサでは、アライメントされていない読み取りを行おうとするとバス エラーが発生しますが、他のプロセッサではそうしても問題ありませんが、パフォーマンスが大幅に低下します。
このため、ほとんどのメモリ割り当てライブラリは、すべての割り当てをワード境界に揃えるように設計されています。これは、32 ビット システムではアドレスの下位 2 ビットが 0 になり (数が 4 の倍数であるため)、64 ビット システムではアドレスの下位 3 ビットが 0 になることを意味します。 0. 多くのデータ構造は、これらの下位ビットを使用して余分な情報を格納することにより、表現を圧縮します。たとえば、赤/黒ツリーの一部の実装では、ノードが赤か黒かを格納するビットをポインターの 1 つの下位ビットに配置し、一部の AVL ツリー (2 ビットの情報を格納する必要がある) はパックします。これらのビットをこれらのポインターの下位ビットに挿入します。一部のガベージ コレクション アルゴリズムでは、同様の手法を使用してマーク ビットを格納します。
編集: C では、一部のコンパイラはuintptr_t
、ポインターを保持するのに十分な大きさの整数を表す型をサポートしています。ポインターを a にキャストuintptr_t
し、変数に対して標準のビット演算子を使用しuintptr_t
てビットを設定またはクリアし、ポインターにキャストして結果を格納できます。C++ では、私の知る限りでは、これにより未定義の動作が発生します。
お役に立てれば!
これは、メモリのブロックを要求すると、アーキテクチャのワードに合わせたブロックで配信されるためです。つまり、ワードの倍数であるメモリ アドレスから開始されます。それがワードの倍数にある場合、それは偶数であり、最初の最下位ビットがオンになることを除外します。32 ビット マシンでは、ワード サイズ チャンクは 4 になり、バイナリの 4 は 100 になるため、最下位から 2 番目のビットがオフになります。
これは、単語との整合性によって私が意味するものの例です。次の構造を検討してください (32 ビットを想定)。
struct sample {
char a;
int b;
char c;
char d;
};
... 7 バイトではなく 8 バイトが必要です (データ構造のアラインメントのため)。
注意:コンパイラはこれに従う必要がありますが、必須ではありません。ほとんどの場合、またはオプションがあります。