Сегодня случайно натолкнулся на статью Применение специальных возможностей GCC в ядре Linux, в которой есть следущие строки: Массивы нулевой длины Согласно стандарту С, для массива необходимо определить как минимум один элемент. Как правило, это требование усложняет проектирование кода. Однако GCC поддерживает концепцию массивов нулевой длины, которые могут быть особенно полезны при определении структур данных. Эта концепция похожа на гибкие элементы массива в ISO C99, но использует другой синтаксис. В следующем примере в конце структуры объявляется массив нулевой длины (из ./linux/drivers/ieee1394/raw1394-private.h). Это позволяет экземпляру этой структуры ссылатся на память, следующую непосредственно за ней. Это может быть полезно, когда вам необходимо иметь переменное количество элементов в массиве. struct iso_block_store { atomic_t refcount; size_t data_size; quadlet_t data[0]; }; Меня удивило предложение "Это может быть полезно, когда вам необходимо иметь переменное количество элементов в массиве", и именно в связи с ним возникло два вопроса: Почему data[0], когда можно воспользоваться классическим data * ? Как для data[0] выделяется память под это самое "переменное количество элементов в массиве", то есть как ведётся с ним работа? Спасибо.
Ответ
Потому что массив при таком определении будет частью структуры, то есть, расположен с ней в общем куске памяти. В случае с quadlet_t *data, для данных необходимо будет выделить новый кусок, отдельный от struct iso_block_store
Например, так:
struct iso_block_store *store =
malloc(sizeof(struct iso_block_store) +
sizeof(quadlet_t) * number_of_data_items);
Обращаться к элементу просто: store->data[i]
Технически говоря, доступ к массиву за пределами объявленного размера есть undefined behaviour (обсуждение на SO). Однако, многие компиляторы (включая gcc и MSVC) ведут ожидаемым образом.
Комментариев нет:
Отправить комментарий