構造物のサイズ
thing *
あなたが参照する は とは 100% 無関係であることに注意してくださいstruct thing
。これはCです。あなたのタグはそう言っています。コードをきれいにコンパイルするには、次のように記述します。
typedef struct thing thing;
struct thing
{
int x;
thing *next;
};
の最小サイズはstruct thing
ですsizeof(int) + sizeof(thing *)
が、構造体はそれよりも大きくなる場合があります。実際、私の (64 ビット) マシンでは、構造体のサイズは 16 バイトですsizeof(int)
が、わずか 4 バイトです。これは、アドレスが 8 バイトでアラインされている必要があるため、int
とポインターの間に 4 バイトのパディングがあるためです。
8 バイト アラインメント
「8 バイト アライン」の意味を説明できますか?
多くの CPU では、N の倍数のアドレスに N バイトの基本型を格納する必要があります。したがって、1 バイトのchar
変数は任意のアドレスに格納できますが、2 バイトのshort
変数は次のアドレスに格納する必要があります。 2 の倍数、4 バイトint
変数は 4 の倍数などのアドレスに格納する必要があります。一部のマシン、特に RISC アーキテクチャでは、間違ったアラインメントで読み取ろうとすると SIGBUS シグナル (およびコア ダンプ) が発生します。それ以外の場合は、正しい結果を得るために CPU が複数の読み取りとビットの調整を行うことになりますが、データが正しく整列されている場合よりもはるかに遅くなります。コンパイラは、これらが高価であることを認識しており、ルールに違反しないようにします。また、コンパイラは、必要に応じて、構造体の先頭以外の場所にパディングを導入して、構造体内の要素が適切に整列され、構造体型の配列の要素が適切に整列されるようにします。
64 ビット コンパイラとデータ構造を考えてみましょう。
struct list
{
struct list *next;
int data;
};
シングルstruct list
はわずか 12 バイト (ポインター用に 8 バイト、データ用に 4 バイト) である可能性がありますが、コンパイラーは最後に 4 バイトのパディングを追加するため、これらの構造体の配列がある場合、配列内の 2 番目の項目は、8 バイトの倍数で正しく配置されます (アドレスは 64 ビット、8 バイト量であるため必要です)。
無限大
サイズはもちろん sizeof(int)+sizeof(thing*) ですが、sizeof(thing*) とは???? それは、int を保持する構造体へのポインターのサイズに、int を保持する別の構造体へのポインターのサイズと、別の構造体へのポインターのサイズを加えたものです。 .....
だから私は事の大きさは無限でなければならないと思います。
ここには無限回帰はありません。構造体のサイズと構造体へのポインターのサイズは、2 つのまったく異なるものです。C は再帰型を許可しません。
struct xyz { int data; struct xyz nested; }; /* Invalid C and C++ and ... */
これには無限の量のメモリが必要であり、仮想メモリでさえシミュレートできません (コンピュータのメイン メモリには、無限に大きなデータ構造のサイズを保持するのに十分なビットがなく、無限に大きな構造自体はなおさらです)。
しかし、問題の構造には構造が含まれていません。構造体へのポインタが含まれています。C 標準では、構造体のすべてのアドレスが同じサイズであることを保証しています (POSIX ではより厳しい要件が課されています。すべてのオブジェクトへのすべてのポインターと関数へのポインターは同じサイズでなければなりません)。そのため、構造体へのポインターのサイズは固定されています — 32 ビット コンパイルでは 4 バイト、64 ビット コンパイルでは 8 バイトです (実際には、理論的には例外がある場合でも)。そして、構造のサイズは固定で有限です。