2
struct thing { 
    int x;
    thing* next;
} 

サイズはsizeof(int)+sizeof(thing*)もちろん ですが、sizeof(thing*)???? それは、int を保持する構造体へのポインターのサイズに、int を保持する別の構造体へのポインターのサイズと、別の構造体へのポインターのサイズを加えたものです。 .....

だから私は事の大きさは無限でなければならないと思います。(これは、数学を専攻する人がプログラミングの本を手に取ったときに起こることです。彼はすべてを極端に論理的に考えて混乱します。)

4

4 に答える 4

2

構造物のサイズ

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 バイトです (実際には、理論的には例外がある場合でも)。そして、構造のサイズは固定で有限です。

于 2013-11-01T05:56:01.470 に答える
1

いいえ、いいえ、いいえ、構造内にある可能性のあるものではなくsizeof(struct thing*)、構造を指すために必要なポインターのサイズです。(たとえば、null ポインターの場合を考えてみましょう。)

于 2013-11-01T05:52:01.543 に答える
1

いいえ、ポインタは固定サイズです。したがって、物のサイズは sizeof (int) + sizeof (ポインター) です。

ニトピッカーのコーナー:

一般的な CPU アーキテクチャのポインタのサイズは、CPU アーキテクチャに応じて 4 バイトまたは 8 バイトです。

ただし、一部の一般的でないアーキテクチャ (DSP チップ、オッドボール マイクロコントローラ、PDP-10、およびその他のワード指向アーキテクチャ) では、ポインタのサイズが異なります。

さらに、一部の一般的でないアーキテクチャでは、異なるサイズのオブジェクトへのポインターは、それ自体が異なるサイズであるため、たとえば、sizeof(char*) != sizeof(int*) のようになります。

さらに、一部のアーキテクチャではビット指向のアドレス指定が許可されているため、多くの場合許可されていないビットフィールドのアドレスを取得できます。(これは C 標準では許可されていませんが、ベンダー拡張として行うことができます。)

于 2013-11-01T05:52:12.653 に答える
1

ポインターのサイズは、ポインターが何を指しているかにはまったく依存しませ。ポインターはワードのサイズになるため、システムでは 4 または 8 バイトになります。

于 2013-11-01T05:52:15.303 に答える