Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
struct book dickens;
и в этой функции появилась бы переменная dickens, имеющая ту же самую форму, что и структура book.
Имя дескриптора указывать не обязательно, но оно должно использоваться, когда шаблон структуры определяется в одном месте, а фактические переменные — в других местах. Мы возвратимся к этому вопросу позже, после того как посмотрим на определение переменных типа структур.
Определение переменной типа структуры
Понятие структура применяется в двух смыслах. Одним из них является “схема структуры” — то, что мы недавно обсуждали. Схема структуры сообщает компилятору, как представлять данные, но она не приводит к выделению пространства в памяти для этих данных. Следующий щаг заключается в создании переменной типа структуры, и в этом состоит второй смысл понятия. Строка программы, создающая переменную типа структуры, имеет вид:
struct book library;
Структуры и другие формы данных 569
Обнаружив эту инструкцию, компилятор создает переменную library. Используя шаблон book, компилятор выделяет память для массива из MAXTITL элементов типа char, для массива из MAXAUTL элементов типа char и для переменной float. Эта память объединена в единую конструкцию под общим именем library, как показано на рис. 14.1. (В следующем разделе объясняется, каким образом при необходимости разделять эту конструкцию.)
Рис. 14.1. Выделение памяти под структуру
В объявлении переменной типа структуры конструкция struct book играет ту же самую роль, что и ключевые слова int или float в более простых объявлениях. Например, можно было бы объявить две переменные типа struct book и даже указатель на структуру такого вида:
struct book doyle, panshin, * ptbook;
Каждая переменная doyle и panshin типа структуры будет иметь три части: title, author и value. Указатель ptbook может указывать на переменные doyle, panshin или на любую другую структуру book. По существу объявление структуры book создает новый тип по имени struct book.
С точки зрения компьютера объявление
struct book library; является сокращением для
struct book {
char title[MAXTITL]; char author[AXAUTL]; float value;
] library; /* объявление с именем переменной */
Другими словами, процесс объявления структуры и процесс определения переменной типа структуры можно объединить в одно действие. Комбинация объявления и определений переменных делает излишним применение дескриптора:
struct { /* дескриптор отсутствует */
char title[MAXTITL]; char author[MAXAUTL]; float value;
} library;
Тем не менее, дескриптор понадобится, если шаблон структуры должен использоваться более одного раза. Можно также применить альтернативный вариант с typedef, рассматриваемый далее в этой главе.
570 глава 14
Есть еще один аспект, касающийся определения переменной типа структуры, который не был задействован в этом примере: инициализация. Давайте взглянем на нее.
Инициализация структуры
Вы уже видели, как инициализировать переменные и массивы:
int count = 0;
int fibo[7] = {0, 1,1, 2,3,5,81};
Можно ли также инициализировать переменную типа структуры? Да, можно. Для инициализации структуры (любого класса хранения ANSI С и последующих стандартов, но исключая автоматические переменные в реализациях, которые предшествуют ANSI С) используется синтаксис, аналогичный применяемому при инициализации массивов:
struct book library = {
"The Pious Pirate and the Devious Damsel",
"Renee Vivotte",
1.95
};
Как видите, используется список разделенных запятыми инициализаторов, заключенный в фигурные скобки. Тип каждого инициализатора должен соответствовать типу члена структуры, который он инициализирует. Следовательно, член title можно инициализировать строкой, а член value — числом. Чтобы сделать эти связи более очевидными, мы выделили для каждого члена отдельную строку инициализации, но компилятору вполне достаточно отделения инициализаторов друг от друга запятыми.
НА ЗАМЕТКУ! Инициализация структуры и продолжительность хранения
В главе 12 упоминалось, что при инициализации переменной со статической продолжительностью хранения (например, статической с внешним связыванием, статической с внутренним связыванием или статической без связывания) должны использоваться константные значения. Это применимо также к структурам. Если вы инициализируете структуру со статической продолжительностью хранения, то значения в списке инициализаторов должны быть константными выражениями. Если продолжительность хранения является автоматической, значения в списке инициализаторов не обязательно должны быть константами.
Доступ к членам структуры
Структура похожа на “супермассив”, в котором один элемент может иметь тип char, другой — float, а следующий — массив элементов типа int. Обращаться к отдельным элементам массива можно с помощью индекса. А как получить доступ к индивидуальным членам структуры? Для этого служит операция членства в структуре — точка (.). Например, library .value — это компонент value структуры library. Конструкцию library .value можно использовать подобно любой другой переменной типа float. Аналогично, library, title можно применять в точности как массив типа char. По этой причине в приведенной выше программе используются такие выражения, как
s_gets(library.title, MAXTITL);
и
scanf("%f", slibrary.value);
По существу .title, .author и .value играют роль индексов для структуры
book.
Структуры и другие формы данных 571
Обратите внимание, что хотя library — это структура, library. value имеет тип float и применяется подобно любой другой переменной типа float. Например, scanf ("%f ", ...) требует адреса ячейки со значением float, и именно таким адресом является Slibrary. float. Здесь операция точки имеет более высокий приоритет, чем операция &, поэтому выражение эквивалентно & (library, float).
При наличии второй переменной структуры того же типа можно воспользоваться тем же самым методом:
struct book bill, newt;
s_gets(bill.title, MAXTITL);
s_gets(newt.title, MAXTITL);
Конструкция .title относится к первому члену структуры book. Следует отметить, что исходная программа выводит содержимое структуры library в двух разных форматах. Это иллюстрирует свободу, доступную при работе с членами структуры.
Инициализаторы для структур
Стандарты С99 и С11 предоставляют назначенные инициализаторы для структур. Синтаксис похож на синтаксис назначенных инициализаторов для массивов. Однако назначенные инициализаторы для структур при идентификации конкретных членов используют операцию точки и имена членов, а не квадратные скобки и индексы. Например, чтобы инициализировать только член value структуры book, можно поступить так:
struct book surprise = {.value = 10.99};
Назначенные инициализаторы можно указывать в любом порядке:
struct book gift = {.value = 25.99,
.author = "James Broadfool",
.title = "Rue for the Toad"};
Как и в случае массивов, обычный инициализатор, следующий за назначенным, присваивает значение члену, который следует за членом, указанным в назначенном инициализаторе. Кроме того, член получает значение, которое было предоставлено последним. Например, взгляните на такое объявление:
Читать дальшеИнтервал:
Закладка: