#arrays #c #pointers #struct #malloc
#массивы #c #указатели #структура #malloc
Вопрос:
Мне нужно иметь глобальный динамический массив указателей, в котором я буду хранить свои структуры, потому что позже мне нужно будет выполнить итерацию по этому массиву, чтобы перечислить всю сохраненную информацию, мне также нужно иметь возможность считывать name
age
job
переменные и с консоли и сохранять их в a person_t
в iterator
массиве.
#include <stdio.h>
#include <stdlib.h>
typedef struct Person
{
char name[30];
int age;
char job[30];
} person_t;
person_t **iterator;
int capacity = 10;
int size = 0;
int main()
{
int i;
*iterator = (person_t *)malloc(capacity * sizeof(person_t));
for (i = 0; i < capacity; i)
{
person_t p;
p.age = i;
*iterator[i] = p;
}
return 0;
}
Я не получаю ошибок / предупреждений при компиляции этого кода (gcc -ansi -pedantic -Wall -Wextra), но когда я пытаюсь его запустить, я Segmentation fault
немедленно получаю.
Комментарии:
1. нет необходимости приводить
malloc
Ответ №1:
Когда вы делаете это:
*iterator = (person_t *)malloc(capacity * sizeof(person_t));
Вы откладываете iterator
, однако в качестве переменной указателя области действия файла она инициализируется значением NULL. Попытка разыменования нулевого указателя вызывает неопределенное поведение.
Я подозреваю, что вам действительно нужен массив структур, а не массив указателей на структуры. В этом случае определите iterator
как:
person_t *iterator;
Затем вы выделяете для него память следующим образом:
iterator = malloc(capacity * sizeof(person_t));
Затем присваивайте элементам массива следующим образом:
iterator[i] = p;
Ответ №2:
Ваша заявленная цель — создать «глобальный динамический массив указателей, в котором я буду хранить свои структуры». Следующая модификация вашего кода (см. Комментарии) сделает это:
person_t p[10] = {0};
int main()
{
int i;
// with declaration: person_t **iterator = NULL;,
//following is all that is needed to create an array of pointers:
iterator = malloc(capacity * sizeof(person_t *));//no need to cast return of malloc
for (i = 0; i < capacity; i)
{
//person_t p;//moved to scope that will exist outside of main()
p[i].age = i;
iterator[i] = amp;p[i];//assign the address of the object to the pointer
//iterator[i] is the ith pointer in a collection of
//pointers to be assigned to point to
//instances of struct person_t
}
//Once all fields are populated (to-do), the following will display the results:
for (i = 0; i < capacity; i)
{
printf("%d) Name: %s Age: %d Job: %sn", i, iterator[i]->name,iterator[i]->age,iterator[i]->job);
}
return 0;
}
Комментарии:
1. Стоит отметить, что «итератор» на самом деле является неправильным, поскольку это основное хранилище для этой коллекции
person_t
.people
имело бы больше смысла, а затем объявить aperson_t *iterator
для использования в качестве временного указателя для фактического перебора коллекцииpeople
.2. @DavidC.Rankin — я не согласен. Однако моя попытка здесь заключалась в том, чтобы использовать строгую буквальную интерпретацию того, что запрашивал OP, и при этом придерживаться описаний переменных OP, что позволяет OP легко отслеживать элементы в запросе с помощью шагов в моей реализации. Использование соглашений об именовании операций помогает с этой целью.
3. Я понимаю, и я согласен, что это помогает отслеживать имена, используемые в вопросе. Вот почему я не предлагал изменения, а просто то, что на это стоило указать, так что, по крайней мере, они осознают, что описательное именование полезно. Комментарий подойдет.
Ответ №3:
вы неправильно выделяете память
Сначала вам нужно выделить память для указателя, который может хранить capacity
номер адреса, т.е. выполненный, iterator = malloc(capacity * sizeof(person_t*));
а затем вам нужно выделить память для хранения каждого элемента структуры, т.е iterator[i] = malloc(sizeof(person_t));
вся malloc
‘отредактированная память должна быть free
‘общей, как только мы закончим с этим.
Кроме того, вы не выполнили проверку ошибок для malloc
‘s , которая оставлена для вас в качестве упражнения.
int main()
{
int i;
// test data
char *names[] = {"ABC", "DEF"};
char *jobs[] = {"Accountant", "Security"};
int ages[] = {50, 60};
// first allocate memory for iterator , which can hold pointers to store iterator poniters
iterator = malloc(capacity * sizeof(person_t*));
for (i = 0; i < capacity; i)
{
// now allocate memory for individual iterator
iterator[i] = malloc(sizeof(person_t));
strcpy(iterator[i]->name,names[i]);
iterator[i]->age = ages[i];
strcpy(iterator[i]->job, jobs[i]);
}
for (i = 0; i < capacity; i)
{
printf("name = %s ", iterator[i]->name);
printf("Age = %d ", iterator[i]->age);
printf("Job = %sn", iterator[i]->job);
}
return 0;
}