Если это экзамен, и вы должны использовать Flexible Array Member, то, как я указал в комментариях и как @rici объяснил в его ответе, цель FAM - предоставить заполнитель для данного type
тогда это позволяет вам выделить хранилище для самой структуры плюс хранилище для некоторого числа вашего типа FAM в одном выделении.Преимущество, которое это дает, состоит в том, что для структуры используется одиночное распределение / одиночное освобождение, а не отдельное выделение, а затем выделение для некоторого числа нужного вам типа.
(до FAM существовало так называемое struct hack , где вместо него использовался массив размером 1
для почти той же цели)
type
имеет решающее значение для того, как вы справляетесь и распределяете свои FAM.В вашем случае ваш FAM равен item *items[];
(массив указателей для типа item
- Item
в вашем коде). Таким образом, вы выделяете для структуры, а затем X
количество указателей на item
.
Чтобы инициализировать каждого члена items
, необходимо присвоить действительный адрес структуре типа item
(или вы можете отдельно выделить, скопировать в новый блок, а затем назначить начальныйадрес для этого блока на указатель в items
) В вашем случае у вас есть массив struct item
, называемый fruits
.Чтобы присвоить items
, вы должны назначить адрес каждой структуры для каждого элемента в items
(помните, что у вас есть хранилище для указателей, а не хранилище для структуры item
- и вы должны обеспечить fruits
остается в области действия на время вашего использования basket
)
Соединяя эти кусочки, вы можете сделать что-то похожее на следующее:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct {
int low, high;
char label[16];
} item;
typedef struct {
size_t length;
item *items[];
} item_coll;
char *find_first_in_range(item_coll *ic, int rlow, int rhigh)
{
for (size_t i = 0; i < ic->length; i++)
if (ic->items[i]->low >= rlow && ic->items[i]->high <= rhigh)
return ic->items[i]->label;
return NULL;
}
int main() {
item fruits[] = {
{10, 20, "Apple"},
{12, 14, "Pear"},
{ 8, 12, "Banana"},
{ 2, 4, "Grape"},
{15, 35, "Watermelon"}
};
size_t nfruits = sizeof fruits/sizeof *fruits; /* avoid magic-numbers */
/* allocate storage for basket + nfruits pointers */
item_coll *basket = malloc (sizeof *basket +
nfruits * sizeof *basket->items);
if (!basket) { /* validate allocation succeeded */
perror ("malloc-basket+5_item_coll");
return 1;
}
basket->length = nfruits; /* assign length */
for (size_t i = 0; i < nfruits; i++) /* assign addresses to structs */
basket->items[i] = &fruits[i];
char *label = find_first_in_range (basket, 12, 15); /* save return */
if (label) /* validate not NULL before printing */
printf ("%s\n", label);
free (basket); /* don't forget to free the memory you allocate */
return 0;
}
( note Я просто использовал typedefs и сам удалил метки структуры - это ваше дело. Кроме того, вы должны проверить возвращаемое значение find_first_in_range
не NULL
перед печатью.)
Пример использования / вывода
Также обратите внимание, что я ограничил диапазон high/low
для
$ ./bin/fam_initialization
Pear
Проверка использования памяти / ошибок
В любом написанном вами коде, который динамически распределяет память, у вас есть 2 обязанностей в отношении любого выделенного блока памяти: (1) всегда сохраняйте указатель на начальный адрес для блока памятитак, (2) он может быть освобожден , когда онбольше не требуется.
Крайне важно, чтобы вы использовали программу проверки ошибок памяти, чтобы убедиться, что вы не пытаетесь получить доступ к памяти или писать за пределами / за пределами выделенного блока, пытаться прочитать или создать условное выражениеперейти к неинициализированному значению и, наконец, подтвердить, что вы освобождаете всю выделенную память.
Для Linux valgrind
- нормальный выбор.Для каждой платформы есть похожие проверки памяти.Все они просты в использовании, просто запустите вашу программу через нее.
$ valgrind ./bin/fam_initialization
==6887== Memcheck, a memory error detector
==6887== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==6887== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==6887== Command: ./bin/fam_initialization
==6887==
Pear
==6887==
==6887== HEAP SUMMARY:
==6887== in use at exit: 0 bytes in 0 blocks
==6887== total heap usage: 1 allocs, 1 frees, 48 bytes allocated
==6887==
==6887== All heap blocks were freed -- no leaks are possible
==6887==
==6887== For counts of detected and suppressed errors, rerun with: -v
==6887== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Всегда подтверждайте, что вы освободили всю выделенную память и нет ошибок памяти.
Посмотрите вещии дайте мне знать, если у вас есть дополнительные вопросы.