Добавление элементов в члены Flexible Array

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

typedef struct School{
    char *name;
    char *courses[]; //Flexible Array Member
}School;

1) Может кто-нибудь показать мне пример того, как я могу добавить элемент к этому элементу с гибкой длиной и распечатать его после сохранения.

2) Я также хотел бы знать, как правильно размещать его. Исходя из того, что я прочитал о гибких членах массива, нам нужно было бы добавить больше места для гибкого члена массива, и я не могу просто использовать sizeof(School);, Моя единственная проблема заключается в том, как узнать, сколько нужно добавить для этого гибкого участника.

3 ответа

Решение

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

typedef struct School {
    char *name;
    int ncourses;
    char *courses[]; //Flexible Array Member
} School;

Скажем, у вас есть 2 школы, одна с 3 курсами, одна с 2. Вы бы распределили структуры следующим образом:

School *mc = malloc(offsetof(struct School, courses) + 3 * sizeof(char *));
mc->name = strdup("Math College");
mc->ncourses = 3;
mc->courses[0] = strdup("Math 101");
mc->courses[1] = strdup("Math 102");
mc->courses[2] = strdup("Math 103");

School *ps = malloc(offsetof(struct School, courses) + 2 * sizeof(char *));
ps->name = strdup("Psycho School");
ps->ncourses = 2;
ps->courses[0] = strdup("Psycho 101");
ps->courses[1] = strdup("Unknown 404");

Как видите, элементы массива переменных доступны так же, как и любые другие элементы массива. malloc call выделяет соответствующий размер в байтах для членов структуры и элементов массива (здесь char * указатели), которые расположены в конце структуры.

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

School create_school(const char *school_name, int ncourses, char *courses[]) {
    School *sp = malloc(offsetof(struct School, courses) + ncourses * sizeof(char *));
    sp->name = strdup(school_name);
    sp->ncourses = ncourses;
    for (int i = 0; i < ncourses; i++) {
        sp->courses[i] = strdup(courses[i]);
    }
    return sp;
}

Точная формула для вычисления необходимого размера вашей структуры:

size_t need = offsetof(struct School, courses) + num_courses * sizeof(char *);

Обратите внимание на использование offsetof, Некоторые люди используют sizeof, но это может привести к накладным расходам памяти из-за заполнения структуры.

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

School *data = malloc(sizeof(*data) + number * sizeof(*(data->courses)));

for (i = 0; i < number; ++i)
{
     const char hello[] = "Hello";
     data->courses[i] = malloc(strlen(hello) + 1));   /* sizeof char is 1 by definition */
     strcpy(courses[i], hello);
}
Другие вопросы по тегам