Элемент гибкого массива в C-структуре

Цитируя из раздела C-std 6.7.2.1,

struct s { int n; double d[]; }; 

Это допустимое объявление структуры. Я ищу практическое применение такого синтаксиса. Чтобы быть точным, как эта конструкция более или менее мощна, чем сохранение двойника * как второго элемента? Или это еще один случай «вы-делаете-он-в-многоразовом»?

Arpan

Ответ на этот вопрос отвечает на часто задаваемые вопросы. Быстрый ответ заключается в том, что эта структура будет включать double массив внутри структуры, а не указатель на массив вне структуры. В качестве быстрого примера вы можете использовать свою структуру, как в этом примере:

 struct s mystruct = malloc(sizeof(struct s) + 5 * sizeof(double)); sn = 12; sd[0] = 4.0; sd[1] = 5.0; sd[2] = 6.0; sd[3] = 7.0; sd[4] = 8.0; 

И так далее – размер массива, который вас интересует, включен в распределение, а затем вы можете использовать его точно так же, как любой массив. Обычно такой тип содержит размер как часть структуры, так как использование трюка + чтобы пропустить массив типа s будет неизбежно осложняться этой ситуацией.

К вашему добавленному вопросу: «Как эта конструкция более или менее мощна, чем сохранение [указателя] как второго элемента?», Это не более мощное само по себе, но вам не нужно держать указатель вокруг, поэтому вы бы сэкономили по крайней мере, столько места – также когда вы копируете структуру, вы также скопировали массив, а не указатель на массив – иногда это было бы тонкое различие, но очень важно другое время. «Вы можете сделать-это-в-многоразовом», вероятно, является хорошим объяснением, но бывают случаи, когда вы специально хотите один дизайн или другой.

Основное преимущество заключается в том, что гибкий элемент массива позволяет вам выделять один блок памяти для массива вместе с другими данными в структуре (с указателем вы обычно должны иметь два отдельно выделенных блока).

Это также полезно при передаче данных по нескольким сетевым протоколам, где входящий stream определяется одинаково – целое число, определяющее длину, за которым следует множество единиц (обычно байтов / октетов) данных. Вы можете (обычно) использовать тип-pun, чтобы наложить структуру с гибким членом массива на буфер, заполненный такими данными, и работать с ним напрямую, вместо того, чтобы анализировать его на части, а затем работать с частями по отдельности.

Вы можете использовать его для добавления полей заголовка в динамически распределенные массивы, наиболее распространенным из которых будет его размер:

 struct int_array { size_t size; int values[]; }; struct int_array *foo = malloc(sizeof *foo + 42 * sizeof *foo->values); foo->size = 42; ... for(size_t i = 0; i < foo->size; ++i) foo->values[i] = i * i; 

Вы могли бы добиться аналогичных результатов, используя вместо этого элемент int * и выделяя массив отдельно, но он будет менее эффективным как с точки зрения памяти (дополнительный указатель, управление кучей для второго блока памяти), так и время выполнения (дополнительная косвенность, второе выделение).

Я видел, как это использовалось в Windows для строк, помеченных по их длине. Символьные данные сохраняются непосредственно после длины в памяти, сохраняя все вместе аккуратно.

 typedef struct { SIZE_T bytes; TCHAR chars[]; } tagged_string; 
Interesting Posts
Давайте будем гением компьютера.