3

C の連結リストの次のフィールドの最下位ビットに関する次のステートメントを見つけました。

「C では、次のフィールドはポインタです。プロセッサのメモリ サブシステムに関連するパフォーマンス上の理由から、メモリはワード境界に割り当てられ、(少なくとも) 次のポインタの 2 つの最下位ビットは 0 です。」

これは本当ですか?もしそうなら、なぜそうなのか理解できません。助けてください。

4

2 に答える 2

5

多くのプロセッサ アーキテクチャは、操作がワード アラインされたアドレスで実行されるように設計されています。たとえば、一部の 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++ では、私の知る限りでは、これにより未定義の動作が発生します。

お役に立てれば!

于 2013-08-11T23:18:03.623 に答える
0

これは、メモリのブロックを要求すると、アーキテクチャのワードに合わせたブロックで配信されるためです。つまり、ワードの倍数であるメモリ アドレスから開始されます。それがワードの倍数にある場合、それは偶数であり、最初の最下位ビットがオンになることを除外します。32 ビット マシンでは、ワード サイズ チャンクは 4 になり、バイナリの 4 は 100 になるため、最下位から 2 番目のビットがオフになります。

これは、単語との整合性によって私が意味するものの例です。次の構造を検討してください (32 ビットを想定)。

struct sample {
  char a;
  int b;
  char c;
  char d;
};

... 7 バイトではなく 8 バイトが必要です (データ構造のアラインメントのため)。

注意:コンパイラはこれに従う必要がありますが、必須ではありません。ほとんどの場合、またはオプションがあります。

于 2013-08-11T23:15:59.067 に答える