Нет, гибкие массивы всегда должны выделяться вручную.Но вы можете использовать calloc
для инициализации гибкой части и составного литерала для инициализации фиксированной части.Я бы обернул это в функцию выделения inline
следующим образом:
typedef struct person {
unsigned age;
char sex;
size_t size;
char name[];
} person;
inline
person* alloc_person(int a, char s, size_t n) {
person * ret = calloc(sizeof(person) + n, 1);
if (ret) memcpy(ret,
&(person const){ .age = a, .sex = s, .size = n},
sizeof(person));
return ret;
}
Обратите внимание, что это оставляет проверку, если выделение завершилось успешно для вызывающей стороны.
Если вам не нужнополе size
, как я включил здесь, макроса было бы достаточно.Только то, что было бы невозможно проверить возврат calloc
перед выполнением memcpy
.Во всех системах, которые я запрограммировал до сих пор, это будет относительно неплохо прервано.Обычно я думаю, что возврат malloc
имеет второстепенное значение , но мнения по этому вопросу сильно различаются.
Возможно, это (в этом особом случае) даст оптимизатору больше возможностей дляинтегрировать код в окружение:
#define ALLOC_PERSON(A, S, N) \
((person*)memcpy(calloc(sizeof(person) + (N), 1), \
&(person const){ .age = (A), .sex = (S) }, \
sizeof(person)))
Редактировать: Случай, когда это может быть лучше, чем функция, когда A
и S
являются константами времени компиляции.В этом случае составной литерал, поскольку он квалифицирован как const
, может быть размещен статически, и его инициализация может быть выполнена во время компиляции.Кроме того, если в коде появятся несколько распределений с одинаковыми значениями, компилятору будет разрешено реализовать только одну единственную копию этого составного литерала.