Динамическое выделение памяти для структуры на языке Си - PullRequest
0 голосов
/ 20 октября 2019

Я разбираюсь с программированием на C и пытаюсь понять, почему я не могу распечатать элемент данных из структуры (struct) после динамического выделения памяти для структуры.

Я попытался распечатать элементы данныхв структуре, чтобы увидеть, какие значения я получаю, но мой код не компилируется, и я получаю ошибку.

 #include <stdio.h>
 #include <stdlib.h>

 typedef struct Collection {

     int age;
     char date[20];
     char name[20];
 } Collection;

 int main(void) {

     int i;
     int n = 10;

     Collection **dataCollection;
     dataCollection = malloc(sizeof(Collection*)*n);
     dataCollection->age = 20;

for(i = 0; i < n; i++) {

    dataCollection[i] = malloc(sizeof(Collection)*n);
    printf("Data collection item: %d\n", dataCollection->age);
}

for(i = 0; i < n; i++)
    free(dataCollection[i]);
   free(dataCollection);
   return 0;
 }

Я получаю следующие ошибки:

practice1019.c:18:20: error: member reference base type 'Collection *' (aka 'struct Collection *')
      is not a structure or union
     dataCollection->age = 20;
     ~~~~~~~~~~~~~~^ ~~~

practice1019.c:23:56: error: member reference base type 'Collection *' (aka 'struct Collection *')
      is not a structure or union
    printf("Data collection item: %d\n", dataCollection->age);

1 Ответ

1 голос
/ 20 октября 2019

Продолжая из комментария, вы не можете назначить dataCollection->age = 20; после простого выделения блока памяти, достаточного для дырки 10 указателей на Collection. Вы выделили память для указателей, но не хранилище для самих структур.

Кроме того, вы должны проверить каждое выделение , например,

    dataCollection = malloc(sizeof(Collection*)*n);

    if (!dataCollection) {  /* validate EVERY allocation */
        perror ("malloc-dataCollection");
        return 1;
    }

Теперь, прежде чем вы сможете присвоить значение элементу любой структуры, вы должны выделить блок памяти для хранения структуры, а затем назначить начальный адрес для этого блока одному из только что выделенных указателей, например,

    for (i = 0; i < n; i++) {
        dataCollection[i] = malloc(sizeof(Collection));
        if (!dataCollection[i]) {   /* ditto */
            perror ("malloc-dataCollection[i]");
            return 1;
        }

( примечание: выше, нет * n после Collection в sizeof(Collection) - или вы будете перерасходовать с коэффициентом 10 в структурном хранилище. ..)

Теперь у вас есть хранилище для структуры, и вы можете использовать элементы (age ниже)

        dataCollection[i]->age = i + 20;
        printf("Data collection[%d] age: %d\n", i, dataCollection[i]->age);
    }

Хорошая работа на free каждого изструктуры, а затем указатели. В целом, вы можете сделать:

#include <stdio.h>
#include <stdlib.h>

typedef struct Collection {
    int age;
    char date;
    char name;
} Collection;

int main (void) {

    int i;
    int n = 10;

    Collection **dataCollection;
    dataCollection = malloc(sizeof(Collection*)*n);

    if (!dataCollection) {  /* validate EVERY allocation */
        perror ("malloc-dataCollection");
        return 1;
    }

    for (i = 0; i < n; i++) {
        dataCollection[i] = malloc(sizeof(Collection));
        if (!dataCollection[i]) {   /* ditto */
            perror ("malloc-dataCollection[i]");
            return 1;
        }
        dataCollection[i]->age = i + 20;
        printf("Data collection[%d] age: %d\n", i, dataCollection[i]->age);
    }

    for(i = 0; i < n; i++)
        free(dataCollection[i]);
    free(dataCollection);
}

Пример использования / Вывод

$ ./bin/datacollection
Data collection[0] age: 20
Data collection[1] age: 21
Data collection[2] age: 22
Data collection[3] age: 23
Data collection[4] age: 24
Data collection[5] age: 25
Data collection[6] age: 26
Data collection[7] age: 27
Data collection[8] age: 28
Data collection[9] age: 29

Посмотрите вещи и дайте мне знать, если у вас есть вопросы.

...