Типы данных, определяемые пользователем

Встроенные типы данных, а также непосредственно основанные на них массивы и указатели могут служить базой для создания новых составных (смешанных) типов данных достаточно сложной конфигурации. Язык C предоставлял пользователю (программисту) возможность создавать свои собственные типы данных: задавать перечисление с помощью ключевого слова enum, определять составной тип (структуру, битовое поле, объединение), вводить новое обозначение типа с помощью ключевого слова typedef.

Перечисленные возможности используют:

· перечисление – список именованных числовых констант целого типа (рассмотрено в разделе 10.2);

· структура – совокупность переменных, объединенных по некоторому признаку, рассматриваемая как нечто единое;

· битовые поля – разновидность структуры, предоставляющая доступ к отдельным битам;

· объединение – разновидность структуры, позволяющая одному участку памяти содержать данные различных типов;

· ключевое слово typedef, которое дает новое имя существующему типу или именует новый составной тип.

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

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

Переопределяемые типы данных

Программист может определить свои типы данных, переименовав уже существующие. Это можно сделать с помощью ключевого слова typedef.

Формат простого переопределения типа:

typedef тип новый_тип ;

Введенное таким образом имя можно использовать так же, как и име­на стандартных типов, например, оператор

typedef unsigned int UINT;

переопределяет тип unsigned int, переименовывая его в UINT. После такого объявления UINT становится синонимом типа unsigned int в программе, например,

UINT i,j;

объявляет переменные i и j только что введенного типа UINT.

Структуры

Не все совокупности данных, используемые в реальной жизни, состоят из однотипных элементов, как массивы. Пример – различные ведомости и таблицы, строки которых содержат числовые и текстовые данные. Составной тип данных, предназначенный для манипулирования подобными данными, называется структурой. Структура языка С аналогична "записи" (record) языка Pascal.

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

struct имя {

тип_1 элемент_1 ;

тип_2 элемент_2 ;

...

тип_n элемент_N ;

};

Ключевое слово struct указывает, что объявляется структура. За ним следует имя шаблона структуры, идентифицирующее описываемую структуру для того, чтобы можно было создавать переменные этого типа. Далее в фигурных скобках располагается описание элементов (полей) структуры, которые, в отличие от элементов массивов, могут быть различных типов.

Пример:

struct Worker { // описание нового типа Worker

int code;

char fio[30];

int age;

double salary;

} ; // описание заканчивается точкой с запятой

Идентификаторы в списке объявлений элементов должны быть уни­кальны. Однако они могут совпадать с идентификаторами элементов других структур и с идентификаторами обычных переменных.

Объявление шаблона структуры описывает определяемый пользователем тип данных, но не создает переменной этого типа. Для создания такой переменной необходимо ее объявить, например, так:

struct Worker worker; // объявление переменной worker типа Worker

В языке С при объявлении переменной структурного типа наличие ключевого сло­ва struct являлось обязательным. В языке С++ это не так, достаточно имени шаблона структуры:

Worker worker;

В этих в объявлениях struct Worker (в C++ – Worker) играет ту же роль, что и, например, int или float в объявлениях обычных переменных. Переменная объявленного структурного типа содержит указанную в описании шаблона последовательность величин заданного типа.

При объявлении переменной структурного типа компилятор выделяет память для каждого элемента структуры. Элементы структуры размещаются в памяти последовательно в том же по­рядке, в котором они объявляются. Па­мять каждому элементу выделяется на границе, соответствующей его типу. Поэтому в памяти могут появиться неиспользуемые неименованные участки между соседними элементами. Вследствие этого размер пе­ременной структурного типа не всегда равен сумме размеров ее эле­ментов. Для определения действительного размера структурной пере­менной следует использовать операцию sizeof.

Как и переменные других типов, структуры при их объявлении можно инициализировать. Для инициализации структуры значения ее элементов перечисляют в фигурных скобках в соответствующем порядке. Например:

struct {

int code;

char fio[30];

int age;

double salary;

} worker = { 3124, "Ivanoff", 31, 3400.55};

Как и для массивов, указывать пустые значения в списке нельзя, недостающие значения принимаются нулевыми, лишние вызывают соответствующее сообщение компилятора об ошибке.

Для доступа к элементам (полям) структуры используется операция . (“точка”, выбор), связывающая имя структурной переменной и имя ее элемента:

int iAge = worker.age;

worker.code = 3125;

strcpy (worker.fio, "Sidoroff");

cout << worker.salary;

Для переменных одного и того же структурного типа определена операция при­сваивания, при этом происходит поэлементное копирование. Так, для

Worker worker2;

worker2 = worker;

элементы worker2 получат значения соответствующих элементов worker.

Массивы структур

Как видно из шаблона структуры Worker, массивы могут быть элементами структур. В свою очередь и переменные одного и того же структурного типа могут объединяться в массивы. Пример объявления массива структур:

Worker staff [100]; // массив из 100 структур типа Worker

При инициализации массивов структур удобно заключать в фигурные скобки список значений для каждой структуры:

Worker worker[2] = { { 3124, "Ivanoff", 31, 3400.55},

{ 3125, "Petroff", 35, 3900.00} };

Можно не структурировать фигурными скобками данные для инициализации, тогда они будут присваиваться полям структур в порядке их расположения.

Пример доступа к полям массива структур:

staff[8].age = 30;

cout <<staff[5].fio;

char c = staff[7].fio[0];

Наши рекомендации