Теперь вы располагаете объемом памяти, которого достаточно для хранения count, average и массива из пяти значений double. Для доступа к этим членам можно применять указатель pf:
pf->count =5; // установка члена count
pf->scores[2] = 18.5; // доступ к элементу члена типа массива
В листинге 14.12 пример продолжает развиваться; гибкий массив получает возможность представлять пять значений в первом случае и девять значений — во втором. Здесь также демонстрируется написание функции для обработки структуры с членом типа гибкого массива.
Листинг 14.12. Программа flexmemb.c

594 глава 14

Ниже показан вывод:
Рейтинги: 20 19 18 17 16
Среднее значение: 18
Рейтинги: 20 19.5 19 18.5 18 17.5 17 16.5 16
Среднее значение: 17
К обработке структур, содержащих члены с типами гибких массивов, предъявляется ряд специальных требований. Во-первых, не используйте присваивание структур для копирования:
struct flex * pfl, *pf2; // *pfl и *pf2 являются структурами
*pf2 = *pfl; // не поступайте так
Такой код привел бы к копированию только членов структуры, которые не относятся к типу гибкого массива. Вместо этого применяйте функцию memcpy(), которая описана в главе 16.
Во-вторых, не используйте такие с труктуры совместно с функциями, которые передают структуры по значению. Причина такого ограничения та же — передача аргумента по значению подобна присваиванию. Вместо этого применяйте функции, которые передают адрес структуры.
В-третьих, не используйте структуру с членом типа гибкого массива в качестве элемента массива или члена другой структуры.
Возможно, вы уже слышали о конструкции, подобной члену типа гибкого массива, которая называется приемом “struct hack". Вместо применения пустых квадратных скобок для объявления члена типа гибкого массива прием “struct hack” предусматривает указание нулевого размера массива. Однако данный прием работал только с конкрет ным компилятором (GCC); он не входил в стандарт С. Подход с использованием члена типа гибкого массива предлагает методику, одобренную стандартом.
Анонимные структуры (С11)
Анонимная структура — это член структуры, который является неименованной структурой. Чтобы посмотреть, как это работает, сначала рассмотрим следующее определение для вложенной структуры:
struct names
{
char first[20];
char last[20];
};
struct person
{
int id;
struct names name; // член, представляющий собой вложенную структуру
};
struct person ted = {8483, {"Ted", "Grass"}};
Структуры и другие формы данных 595
В этом примере член name — это вложенная структура, и для получения доступа к "Ted" можно было бы применить выражение наподобие ted.name, first:
puts(ted.name.hrst);
Стандарт C11 позволяет определять структуру person, используя в качестве члена вложенную неименованную структуру:
struct person
{
int id;
struct {char first[20]; char last[20];}; // анонимная структура
};
Эту структуру можно было бы инициализировать в той же манере:
struct person ted = {8483, {"Ted", "Grass"}};
Но доступ к членам упрощается, поскольку для этого применяются имена членов вроде first, как если бы они были членами person:
puts(ted.hrst);
Разумеется, можно было бы просто сделать first и last непосредственными членами структуры person, избавившись от вложенной структуры. Средство анонимности более полезно с вложенными объединениями, которые будут обсуждаться далее в главе.
Функции, использующие массив структур
Предположим, что имеется массив структур, который необходимо обработать с помощью функции. Имя массива — это синоним его адреса, так что его можно передавать функции. Вдобавок функция нуждается в доступе к шаблону структуры. Чтобы продемонстрировать, как это работает, в листинге 14.13 программа финансового анализа расширена с целью обслуживания двух человек, поэтому в ней присутствует массив из двух структур funds.
Листинг 14.13. Программа funds4.c

596 глава 14

Вот вывод программы:
Общая сумма на счетах у Джонсов составляет $20000.00.
Имя массива jones является его адресом. В частности, это адрес первого элемента массива, которым представляет собой структуру jones [0]. Таким образом, первоначально указатель money задается следующим выражением:
Читать дальше