#c #arrays #pointers #struct
#c #массивы #указатели #структура
Вопрос:
Я пытаюсь понять, как правильно инициализировать структуры, которые содержат другие структуры (особенно массивы структур!). Я сделал этот небольшой обзор, представляющий мое текущее понимание, и хотел спросить, является ли это правильным или неправильным способом сделать:
(Обратите внимание, что для краткости методы уничтожения и проверки malloc() опущены.)
Простейшая структура содержит только статические переменные:
typedef struct simple {
int variable;
} Simple;
Simple *create_simple(int value) {
Simple *simple = malloc(sizeof(Simple));
simple->variable = value;
return simple;
}
Использование динамических переменных, таких как массивы, требует дополнительного выделения:
typedef struct array {
size_t length;
int *element;
} Array;
Array *create_array(size_t length) {
Array *array = malloc(sizeof(Array));
array->length = length;
array->element = malloc(length * sizeof(int));
return array;
}
То же самое касается структур, содержащих указатели на другие структуры. В этом случае нам нужно выделить память для внутренней структуры отдельно:
typedef struct container {
Simple *internal;
} Container;
Container *create_container(int value) {
Container *container = malloc(sizeof(Container));
// Is this correct? Or should I just malloc(sizeof(Simple))?
container->internal = create_simple(value);
return container;
}
Более сложной является структура, содержащая динамический массив структурных указателей:
typedef struct struct_array {
size_t length;
Simple **element;
} StructArray;
StructArray *create_struct_array(size_t length) {
StructArray *structArray = malloc(sizeof(Array));
structArray->length = length;
// Would I alternatively need to loop over
// the array and call create_simple() on each index?
structArray->element = malloc(length * sizeof(Simple));
return structArray;
}
Теперь глубина вложенности структур может быть любой:
typedef struct complex_container {
size_t length;
StructArray *element;
} ComplexContainer;
ComplexContainer *create_complex_container(size_t length) {
ComplexContainer *complexContainer = malloc(sizeof(ComplexContainer));
complexContainer->length = length;
// Is this valid? My create_struct_array function should
// allocate the memory?
complexContainer->element = create_struct_array(length);
return complexContainer;
}
Комментарии:
1. Что заставляет вас думать, что это неверно?
2. В основном вопрос, использовать ли мои функции create внутри других функций create ИЛИ malloc внутри них.
3. И если не было бы лучше использовать массивы внутри определений структур вместо только указателей
4. Распространенной идиомой является использование sizeof object вместо sizeof (тип объекта). В долгосрочной перспективе это безопаснее, на случай, если объект меняет типы. Поэтому вместо этого напишите «foo * p = malloc(sizeof * p);». Имена ваших переменных слишком длинные и делают строки длиннее, чем они должны быть. В приведенных выше фрагментах это не представляет большой проблемы, но может снизить качество кода при обработке ошибок и добавлении большего количества элементов структуры.