结构的指针数组

时间:2012-02-27 19:02:56

标签: c

我有一个像这样的结构

typedef struct person {
 int id;
 char name[20];
} Person;

然后,在函数之外,我有一个指向这些结构的指针数组,就像这样

Person **people;

然后在函数中我将这些人添加到数组中(在循环中)

Person person;

for (i = 0; i < 50; i++)
{
  person.id = i;
  person.name = nameArray[i];
  people[i] = &person;
}

person正被添加到people数组中,但是当(在VS2010中)我转到“监视”屏幕并输入people, 50时 我只是在每个插槽中看到相同的person,就像添加下一个人一样,它也会改变以前的所有内容。我在这里做错了什么?

另外,要检索某个人的姓名,这是正确的语法吗?

people[0] -> name;或者是people[0][0].name

谢谢!

6 个答案:

答案 0 :(得分:9)

你期待什么?您正在使所有指针指向相同的Person。当person超出范围时,数组中的所有指针(都是相同的)将无效并指向释放的内存块。您必须在循环的每次迭代中使用malloc来分配动态存储并创建Person,直到free它才会消失:

for (i = 0; i < 50; i++)
{
  Person *person = malloc(sizeof(Person));
  person->id = i;
  person->name = nameArray[i];
  people[i] = person;

  /* or:
  people[i] = malloc(sizeof(Person));
  people[i]->id = i;
  people[i]->name = nameArray[i];

  it does the same thing without the extra temporary variable
  */
}

// then when you are done using all the Person's you created...
for (i = 0; i < 50; ++i)
    free(people[i]);

或者,你可以拥有一个Person而不是Person*的数组,而你正在做的事情会起作用:

Person people[50];

Person person;

for (i = 0; i < 50; i++)
{
  person.id = i;
  person.name = nameArray[i];
  people[i] = person; // make a copy
}

通过这种方式,您无需free任何事情。

答案 1 :(得分:2)

  

我只是在每个位置都看到同一个“人”......

是的,因为你每次都使用相同的Person。你重新分配其成员,所以最后的任务分配,你的指针都指向同一块内存。

还要意识到您正在存储具有自动存储持续时间的变量的地址(即,已分配堆栈)。当函数退出并在以后解除引用任何指针时,(可能)将清除该内存将导致未定义的行为。

如果需要在函数中初始化数组并在函数退出时保持有效,则应使用动态分配。

答案 2 :(得分:1)

你必须为每个人分配内存:

for (i = 0; i < 50; i++)
{
  people[i] = (person*)malloc(sizeof(person)); // dynamic memory allocation
  people[i]->id = i;
  people[i]->name = nameArray[i];
}

&person的地址person在原始版本中没有变化,所以你有一堆指针指向相同的数据,每次迭代都会改变。

答案 3 :(得分:1)

由于您编写此方法的方式,您已将每个指针初始化为同一个Person实例,请检查:

Person person; // this allocates a single person

for (i = 0; i < 50; i++)
{
  person.id = i;
  person.name = nameArray[i];
  people[i] = &person;
}

您需要做的是动态分配每个人,如下所示:

for (i = 0; i < 50; i++)
{
  Person* person = (Person*)malloc(sizeof(Person));
  person->id = i;
  person->name = nameArray[i];
  people[i] = person;
}

完成后不要忘记释放所有内存,所以在代码结束时:

int i;
for (i=0; i<50; i++)
  free(people[i]);
free(people);

答案 4 :(得分:0)

您需要确保为每个person分配空间。您现在的代码只有一个person结构,您正在重用它,所有这些指针都指向同一个地址。

答案 5 :(得分:0)

其他答案都是正确的。我唯一可以添加的是,除了不创建新的Person之外,当你应该使用堆时,你也在堆栈上分配它。确保您了解为什么以下对您现有代码的“快速更改”是错误的:

for (i = 0; i < 50; i++)
{
  Person person;   /* <--- BAD. Make sure you understand why. */

  person.id = i;
  person.name = nameArray[i];
  people[i] = &person;
}

每次使用您创建人物的旧方式创建一个新的Person。同样,请确保您理解为什么这是错误的,其他答案(使用malloc)是正确的。