Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Члены с типами гибких массивов (С99)
В стандарте С99 предлагается новое средство, которое называется членам типа гибко го массива. Оно позволяет объявлять структуру, последний член в которой является массивом со специальными свойствами. Одно из специальных свойств заключается в том, что такой массив не существует — во всяком случае, не появляется немедленно. Второе специальное свойство состоит в том, что при наличии корректного кода член типа гибкого массива можно использовать, как если бы он существовал и имел нужное количество элементов. Возможно, это звучит несколько своеобразно, так что давайте рассмот рим таги по созданию и применению структуры с членом типа гибкого массива.
Для начала ниже представлены правила, регламентирующие создание члена типа гибкого массива.
• Член типа гибкого массива должен быть последним в структуре.
• В структуре должен присутствовать, по крайней мере, еще один член другого типа.
• Гибкий массив объявляется подобно обычному массиву, но с пустыми квадратными скобками.
Вот пример, иллюстрирующий эти правила:
struct flex
{
int count;
double average;
double scores!]; // член типа гибкого массива
};
Если вы объявили переменную типа struct flex, то не можете использовать член scores, т.к. память для него не зарезервирована. На самом деле, даже не подразумевается, что вы будете объявлять переменные типа struct flex. Вместо этого предполагается, что вы объявите указатель на тип struct flex, а затем с помощью malloc() выделите область памяти, достаточную для хранения обычного содержимого struct flex, плюс дополнительное пространство, которое необходимо для члена с типом гибкого массива. Например, пусть вы хотите, чтобы член scores представлял массив из пяти значений double. В этом случае понадобится поступить так:
struct flex * pf; // объявление указателя
Структуры и другие формы данных 593
// запрос области памяти для размещения структуры и массива pf = malloc(sizeof(struct flex) + 5 * sizeof(double));
Теперь вы располагаете объемом памяти, которого достаточно для хранения 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 задается следующим выражением:
money = &jones[0];
Поскольку money указывает на первый элемент массива jones, то money [0] — это еще одно имя первого элемента массива. Аналогично, money [1] — второй элемент массива. Каждый элемент является структурой funds, поэтому для каждого из них можно применять операцию точки (.), чтобы обращаться к членам структуры.
Читать дальшеИнтервал:
Закладка: