Объединение одного элемента не имеет смысла.Цель объединения - служить своего рода полиморфной структурой.Доступ к членам структуры осуществляется по смещению, поэтому невозможно поместить неполную структуру или массив в середину структуры.
Например,
struct foo { int a; int b[]; int c; };
В этом примере невозможно длякомпилятор для определения адреса c
, поскольку размер b
может изменяться во время выполнения.Но если вы поместите неполный массив в конец, все адреса членов структуры могут быть определены по адресу начала структуры.Имейте в виду, что указатели являются просто адресами, поэтому вы можете иметь любые указатели на любые структуры, и все смещения могут быть определены, но вам придется иметь дело с дополнительными ресурсами alloc / free.
Когда вы создаете объединениеВы говорите компилятору Эй!У меня есть эти члены, зарезервируйте достаточно места для меня, чтобы я мог рассматривать эту переменную как foo или bar .Другими словами, компилятор примет самый большой член объединения, и это будет размер объединения.Обычно объединение используется для представления нескольких типов значений.
typedef union { int integer, float real, char *string } value_type;
Таким образом, вы можете трактовать value_type
как int
, float
или char
указатель.Ваш код должен знать, как обращаться с каждым членом, но компилятор позаботится о том, чтобы при выполнении malloc(sizeof value_type)
у вас было достаточно места для типов дерева.
Теперь ваша проблема.Вы хотите скрыть детали реализации.Обычно это делается путем объявления типа или структуры не полностью в заголовке и полностью только в ваших объектных файлах.Из-за этого, когда пользователь включает ваш заголовок, вся информация, которую имеет компилятор, равна struct my_struct;
.Он не может определить размер my_struct
, поэтому вы не можете выделить его как malloc(sizeof struct my_struct)
.Кроме того, поскольку у пользователя нет определений членов, он не может испортить внутреннюю структуру struct.
Работая так, вам нужно будет предоставить пользователю функции для выделения и освобождения my_struct
, например struct my_struct *foo = my_struct_new()
и my_struct_destroy(foo)
.
Вы уже делаете это.Чтобы справиться с проблемой struct inotify
, я бы сделал один из них.
(1) ОС Surround, специфичная для #ifdef
для этой ОС, так что event_t
имеет только правильных членов, определенных в зависимости отоперационная система.Вам понадобится #ifdef
для ваших функций.Это дает преимущество, заключающееся в том, что в конечном двоичном коде остается бесполезный код, поэтому занимает меньше места.
(2) Имейте указатели на структуры, специфичные для ОС, и позволяйте среде выполнения решать, что делать.Это легче поддерживать.