Страницы

Поиск по вопросам

среда, 5 февраля 2020 г.

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

#c #memory #struct #memory_management


Всем, доброго времени суток! Продолжаю своё медленное, но упорное знакомство с СИ.

Как правильней всего выделить память под структуру, в которой есть поле... Не уверен
что правильный термин, но что-то вроде динамического поля. Смотрим код ниже.

typedef struct
{
   int count;
   char **arrays;
} _array_strs;

_array_strs *getArrayFromFile()
{
   FILE *fd = getFile(STORAGE, "r");
   char sym;
   char **arrays = (char **)getPtrMatrix(&sym, COUNT_WORDS, BUFF_WORD); 

   struct _array_strs *array_strs = (struct _array_strs *)calloc(sizeof(arrays) +
sizeof(int), sizeof(struct array_strs));
   int i = 0;
   while (!feof(fd)) {
      fgets(arrays[i], BUFF_WORD, fd);
      i++;
   }

   array_strs->count = i;
   array_strs->arrays = arrays;

   fclose(fd);

   return array_strs;
}


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

src/search.c: In function ‘getArrayFromFile’:
src/search.c:32:101: error: invalid application of ‘sizeof’ to incomplete type ‘struct
array_strs’
 struct _array_strs *array_strs = (struct _array_strs *)calloc(sizeof(arrays) + sizeof(int),
sizeof(struct array_strs));
                                                                                
                ^
src/search.c:39:12: error: dereferencing pointer to incomplete type ‘struct _array_strs’
 array_strs->count = i;
        ^
src/search.c:44:9: warning: return from incompatible pointer type [-Wincompatible-pointer-types]
 return array_strs;


Буду рад любой помощи компетентных специалистов. Всем добра!
    


Ответы

Ответ 1



Во-первых, у вас в программе нет такого типа, как struct _array_strs. Поэтому "выделить под него память" у вас не получится. При таком объявлении типа, как у вас, тип вашей структуры называется _array_strs, а не struct _array_strs. Чтобы получить тип struct _array_strs объявление должно быть таким struct _array_strs { int count; char **arrays; }; Вы можете совместить оба варианта typedef struct _array_strs { int count; char **arrays; } _array_strs; что сделает _array_strs и struct _array_strs синонимами. Однако использовать эти имена вперемешку не рекомендуется. Выберите одно. Что характерно, в объявлении функции getArrayFromFile у вас использовано правильное имя типа для вашего исходного варианта (просто _array_strs), но затем в коде вдруг непонятно откуда полез какой-то struct _array_strs. Почему? В общем, сначала определитесь, как именно вы хотите называть свой тип и соответствующим образом исправьте его объявление и ссылки на его название в коде. Во-вторых, в текущей версии под сам объект _array_strs выделить память несложно _array_strs *array_strs = malloc(sizeof *array_strs); ... array_strs->count = i; array_strs->arrays = arrays; и все. У вас же там под calloc понаписана какая-то бессмысленная каша. Если вам зачем-то хочется воспользоваться именно calloc, то _array_strs *array_strs = calloc(1, sizeof *array_strs); ... Имейте в виду, что ваше "динамическое поле arrays" это никакое не "динамическое поле", а обычный указатель. На выделение памяти для самой структуры оно никак не влияет вообще. В вашем коде подразумевается, что память для char **arrays выделена где-то внутри getPtrMatrix и выделена правильно. Не ясно только, почему на результат getPtrMatrix сделан явный каст (char **). Почему? В-третьих, в языке С объявления функции со списком параметров () являются deprecated. Возьмите в привычку писать (void). Хотя функция без параметров - это в большинстве случаев странно. P.S. Ну и, конечно, "классика жанра" - цикл с предусловием while (!feof(fd)), который приведет к вопросам типа "почему у меня array_strs->count на единицу больше, чем надо".

Комментариев нет:

Отправить комментарий