Создание массива структуры внутри другой структуры

#c #arrays #struct

#c #массивы #структура

Вопрос:

У меня проблемы с кодом:

 typedef struct{
    int a;
    int b;
} Passenger;

typedef struct{
    int amount;
    Passenger bus_array[amount];
} Bus;
  

Здесь не указано количество.

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

1. Нет, это было бы не так. Фактически, вы не можете объявить такую структуру, потому что компилятор не будет знать, сколько места зарезервировать для нее при создании ее экземпляра. Вы должны использовать указатель и распределять массив динамически. Вы, скорее всего, изменили бы amount в функции, которая устанавливает ammount [sic] и освобождает старую память, а затем выделяет новую память. Это было бы в направлении C (классы — это структуры данных с операциями над ними).

2. Возможно, то, что вы ищете, является гибким элементом массива ?

3. Спасибо, Питер, не мог бы ты быть таким добрым и помочь мне выделить память? я знаю, как использовать malloc для типов данных int или double, но не для типа данных struct : (

4. Когда вы выделяете память с помощью malloc для массива int , вы используете sizeof(int) для размера элемента, верно? То же самое происходит и со структурами, но тип такой, например struct Passanger , что означает, что вы используете sizeof(struct Passanger) .

5. @Someprogrammerdude Я не знал о гибких элементах массива (только о взломе до C99 с автоматическим расширением конечных массивов). Таким структурам всегда нужно, чтобы их пространство распределялось динамически, что подразумевает, среди прочего, что они не могут находиться в массиве, верно, потому что их sizeof() неверно (эй, это sizeoff() !)? (За исключением массива нулевого размера.)

Ответ №1:

У вас есть две альтернативы, обе предполагают динамическое выделение памяти. Большая разница в том, какую структуру вы выделяете динамически.


Первой альтернативой является использование указателя вместо массива:

 typedef struct{
    int amount;
    Passenger *bus_array;
} Bus;
  

Как только вы узнаете значение amount , вы можете выделить память для bus_array :

 Bus my_bus;
bus.amount = get_passenger_amount();
bus.bus_array = malloc(bus.amount * sizeof(Passenger));
  

Второй альтернативой является использование гибкого элемента массива (как я упоминал в комментарии):

 typedef struct{
    int amount;
    Passenger bus_array[];
} Bus;
  

Затем вам нужно выделить Bus структуру динамически:

 int amount = get_passenger_amount();

Bus *my_bus = malloc(sizeof(Bus)   amount * sizeof(Passenger));
my_bus->amount = amount;
  

Между двумя методами есть некоторые различия, которые, возможно, стоит отметить. Наиболее важным является то, что первый метод выполняет два отдельных выделения: одно для Bus структуры, а другое для bus_array . Во втором методе существует только одно комбинированное выделение для всей Bus структуры, а также bus_array .

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

1. Большое вам спасибо! 🙂

2. Структура ‘Bus’ из первого варианта достаточно мала, чтобы передаваться по значению в качестве параметра / возвращаемого значения. Таким образом, обычно это также одно выделение

Ответ №2:

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

 typedef struct{
  int amount;
  Passenger *bus_array;
} Bus;

Bus emptyBus = { 0, NULL}; // use this to initialize new buses so that pointer and amount are zero.

void changeAmount(Bus *bus, int amount)
{
  bus->amount = amount;
  free(bus->bus_array); // freeing a null pointer is OK.
  bus->bus_array = malloc(sizeof(Passenger)*amount);
}
  

Ответ №3:

Здесь

 typedef struct{
  int amount;
  Passenger bus_array[amount];
} Bus;
  

Когда компилятор видит приведенную ниже инструкцию

 Passenger bus_array[amount];
  

он не знает, для какого объема памяти выделить, bus_array потому что amount на данном этапе компилятору это неизвестно. Следовательно, это выдает ошибку.

Вместо

 Passenger bus_array[amount];
  

вы можете использовать

 Passenger *bus_array;
  

и позже вы можете выделить память на bus_array равную amount байтам, когда компилятор знает, что такое amount .

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

1. Спасибо! Я продолжу, используя этот метод 🙂