#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. Спасибо! Я продолжу, используя этот метод 🙂