malloc массив структур в структуре

У меня есть структура, называемая курсом, и каждый курс имеет несколько узлов (еще один узел структуры).

Количество узлов, которые он имеет, варьируется, но мне дается это число из файла, из которого я читаю эту информацию, поэтому это число находится в переменной.

Поэтому мне нужен malloc внутри структуры. Но я в замешательстве. Я знаю, что у вас могут быть массивы в структурах, но я не знаю, куда поместить код, который создает массив malloc, поскольку моя структура находится в моем заголовочном файле. Вот мой код на данный момент. Я понимаю, что это выглядит неправильно, я просто не знаю, как это исправить и где инициализировать массив malloc.

struct course {
    char identifier[2];
    int num_nodes;
    struct node *nodes;
    nodes = (struct nodes*)malloc(num_nodes*sizeof(struct node));
};

struct node {
    int number;
    char type[2];
};

Я хочу иметь возможность сделать что-то вроде:

struct node a_node;
struct course a_course;

a_course.nodes[0] = a_node;

и т.д...

Я мало использовал C, это первый раз, когда я пытался использовать динамические массивы в C. Весь мой опыт связан с Java, и, конечно же, Java не использует указатели в так же, как C, поэтому для меня все это немного запутанно.

Так что некоторая помощь будет высоко оценена, большое спасибо :)


person DanMc    schedule 06.12.2012    source источник
comment
Один из способов - сделать это, как simonc описывает в своем ответе. Я просто хочу ответить на ваш вопрос о том, куда поместить вызов malloc: просто сделайте это сразу после того, как вы выделите память для основной структуры. Псевдо: a = malloc(mother_struct); a->baby = malloc(baby_struct); :-)   -  person Jite    schedule 06.12.2012


Ответы (3)


Самый простой подход — создать функцию, которая инициализирует структуру:

void init_course(struct course* c, const char* id, int num_nodes)
{
    strncpy(c->identifier, id, sizeof(c->identifier));
    c->num_nodes = num_nodes;
    c->nodes = calloc(num_nodes, sizeof(struct node));
}

Для симметрии вы также можете определить деструктор

void destroy_course(struct course* c)
{
    free(c->nodes);
}

Они будут использоваться как

struct course c;
init_course(&c, "AA", 5);
/* do stuff with c */
destroy_course(&c);
person simonc    schedule 06.12.2012
comment
Просто обратите внимание, что в примере использования структура курса помещается в стек, а не в кучу (как если бы она была распределена). Я бы посоветовал вам очистить память, выделенную внутри функции init_course. - person Jite; 06.12.2012
comment
@Jite Извините, я не слежу. Вы имеете в виду, что член nodes должен очистить свою память? - person simonc; 06.12.2012
comment
Да, это правильно. В вашем первоначальном решении вы использовали malloc, но теперь, когда вы используете calloc, это помогает вам. - person Jite; 06.12.2012

Назначение malloc (или calloc, который я предпочитаю использовать для структур) — динамическое выделение памяти во время выполнения. Итак, ваша структура должна выглядеть так, поскольку это определение объекта:

struct course {
    char identifier[2];
    int num_nodes;
    struct node *nodes;
};

Где-то еще в вашей программе, которая использует структуру курса, вам нужно будет выделить память (i) для любых объектов курса, которые вы создаете, и (ii) любых узловых объектов в этом курсе.

e.g.

main()
{
   // lets say 1 course
   struct course *my_course;
   my_course = calloc(1, sizeof(struct course));

   // lets say 3 nodes in that course
   struct node *my_nodes;
   my_nodes = calloc(3, sizeof(struct node));

   my_course.num_nodes = 3;
   my_course.nodes = my_nodes;

   //...
   // clean up
   free(my_nodes);
   free(my_course);
}

Теперь ты в порядке. Обязательно освободите память перед выходом.

person Steve Walsh    schedule 06.12.2012

также можно напрямую выделить структуры в структурах следующим образом:

сначала объявите свою структуру:

struct course {
    char identifier[2];
    int num_nodes;
    struct node *nodes;
};

то в вашей программе

main(){ 
    int i;
    struct course *c;
    c = malloc(sizeof(struct course));
    c->num_nodes = 3;
    c->nodes = malloc(sizeof(struct node)*c->num_nodes);

    for(i=0; i<c->num_nodes; i++) 
        c->nodes[i] = malloc(sizeof(struct node));

    //and free them this way
    for(i=0; i<c->num_nodes; i++) 
        free(c->nodes[i]);
    free(c->nodes);
    free(c);


}

или сделайте это так, как вам нравится

person Neo    schedule 06.12.2012
comment
Здесь есть пара серьезных проблем. nodes — это node*, но вы распределяете его на основе размера несвязанного struct course. Позже вы попытаетесь освободить каждый элемент массива nodes — это не удастся, поскольку был выделен сам массив, а не его отдельные элементы. - person simonc; 07.12.2012
comment
Спасибо, но вы применили только одно из изменений. Вам нужно только вызвать free(c->nodes); — вместо этого вы по-прежнему пытаетесь освободить каждый элемент внутри c->nodes. (Как правило, для каждого malloc требуется ровно один free. В настоящее время ваш код имеет 1 malloc, но num_nodes вызывает free.) - person simonc; 07.12.2012