0

私は「LearnCtheHard Way」を読んでいて、誰かが詳細に説明してくれることを望んでいた興味深い問題に遭遇しました。基本的な演習は、Person構造体の例を含む構造体を使用することでした。最初のケースでは、コンストラクター風のメソッド(誰かが:D側で説明してもかまわないのであれば、チュートリアルがこのようにした理由は正確にはわかりません)と次のような構造体がありました。

struct Person {
  char *name;
  int age;
  int height;
  int weight; 
};

struct Person *Person_create(char *name, int age, int height, int weight) 
{
  struct Person *who = malloc(sizeof(struct Person)); 
  assert(who != NULL);

  who->name = strdup(name);
  who->age = age; 
  who->height = height;
  who->weight = weight;
}

残りのコードとともに、これは問題なく実行されますが、次のようなこれらの構造体へのポインタのメモリ位置を出力すると、次のようになります。

int main(int argc, char* argv[]) {
     struct Person *joe = Person_create("joe alex", 12, 80, 100);
     struct Person *joe = Person_create("frank blank", 20, 72, 140);
}

それらのメモリ値の差は常に正確に40です。これと比較して、次のような構造体コンストラクタの実装は次のようになります。

 struct Person{//is the same as above};

 struct Person Person_create (char* name, int age, int height, int weight) {
  struct Person newPerson;
  newPerson.name = name; //and so on

  return newPerson
 }

上記と同じ値で初期化されたjoeとfrankのメモリ位置を上記の実装で出力すると、それらのメモリ位置の差は常に20であるように見えます。

アセンブリを少し勉強しましたが、コンパイラが構造体のデータ型に従ってメモリのブロックを割り当てることを知っているので、考えていました。どちらの実装でも、char配列には非常に多くの文字があるため、n文字*1=文字スペース、そして私は3つのintを持っているので、3 * 4 = 12; 12 + 9(Joe Alex \ 0 right?)= 21..おそらく\0を間違えたので、20かそこらに等しいのですが、構造体の特定のメモリサイズに関係なく、なぜ2つなのかということにもっと興味があります。実装が異なれば、メモリのサイズも異なります(私の理解では、メモリコストはかなりの量になります)。

4

2 に答える 2

1

最初のケースでは、4 つの動的割り当てが行われstrdupますmalloc。構造体アドレスの違いは、最初の構造体と 2 番目の構造体の前に割り当てられたメモリの量を大まかに示しています[*]

2 番目のケースでは、動的割り当ては行われませんがPerson、スタック上に 2 つのオブジェクトを作成したとします。

struct Person joe = Person_create("joe alex", 12, 80, 100);
struct Person frank = Person_create("frank blank", 20, 72, 140);

それらのアドレスの違いは、最初のアドレスが占めるメモリ量を大まかに示しています[*]。

文字列をコピーしていないため、文字列リテラルを名前として使用するか、Person構造体とは別にメモリを管理する必要があります。文字列データは--の一部ではありませstruct Personん。文字列データではなく、ポインターnewPerson.name = nameを格納するだけです。

これは、ファイルまたは端末から名前を読み取り始めるとすぐに厄介になります。とにかくそれらを動的に割り当てる必要があるため、メモリを節約することはできませんが、より多くのコードを記述する必要があります。演習にはおそらくその名前のPerson_Destroy関数が含まれてfreeいるため、 のユーザーはそれstruct Personについて個別に心配する必要はありません。

[*] 実装がこれらのものを次々に割り当てる必要がないことを除いて、あなたのメソッドは一般的に機能しません。この場合、たまたま、割り当てが作成した順序で配置されるという理論と一致する結果が得られます。

于 2012-05-24T09:33:01.197 に答える
0

2 つの方法は、使用する必要がある方法が大きく異なります。

定義:
struct Person *Person_create(char *name, int age, int height, int weight)
使用:
struct Person *p = Person_create(...);
関数Person_createは構造体を割り当てます。この構造体の場所は、関数の実装によって異なります。呼び出し元は、person 構造体全体ではなく、このメモリへのポインターを定義するだけで済みます。

定義:
struct Person Person_create (char* name, int age, int height, int weight)
使用:
struct Person p = Person_create(...);
ここで、呼び出し元は、ポインターだけでなく、person 構造体全体を割り当てました。関数が呼び出されると、関数が返すデータが呼び出し元の person 構造にコピーされます。したがって、構造体の場所は呼び出し元によって異なります。

于 2012-05-24T09:41:47.680 に答える