Опубликован: 26.06.2003 | Уровень: для всех | Доступ: свободно
Лекция 8:

Производные типы данных

< Лекция 7 || Лекция 8: 1234 || Лекция 9 >

Структуры

Структуры – это не что иное, как классы, у которых разрешен доступ ко всем их элементам (доступ к определенным атрибутам класса может быть ограничен, о чем мы узнаем в лекции 11). Пример структуры:

struct Record {
     int number;
     char name[20];
};

Так же, как и для классов, операция " ." обозначает обращение к элементу структуры.

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

struct {
     double x;
     double y;
} coord;

Обратиться к атрибутам переменной coord можно coord.x и coord.y.

Битовые поля

В структуре можно определить размеры атрибута с точностью до бита. Традиционно структуры используются в системном программировании для описания регистров аппаратуры. В них каждый бит имеет свое значение. Не менее важной является возможность экономии памяти – ведь минимальный тип атрибута структуры это байт ( char ), который занимает 8 битов. До сих пор, несмотря на мегабайты и даже гигабайты оперативной памяти, используемые в современных компьютерах, существует немало задач, где каждый бит на счету.

Если после описания атрибута структуры поставить двоеточие и затем целое число, то это число задает количество битов, выделенных под данный атрибут структуры. Такие атрибуты называют битовыми полями . Следующая структура хранит в компактной форме дату и время дня с точностью до секунды.

struct TimeAndDate
{
unsigned hours    :5; // часы от 0 до 24 
unsigned mins     :6; // минуты 
unsigned secs     :6; // секунды от 0 до 60
unsigned weekDay  :3; // день недели
unsigned monthDay :6; // день месяца от 1 до 31
unsigned month    :5; // месяц от 1 до 12
unsigned year     :8; // год от 0 до 100  
};

Одна структура   TimeAndDate требует всего 39 битов, т.е. 5 байтов (один байт — 8 битов). Если бы мы использовали для каждого атрибута этой структуры тип char, нам бы потребовалось 7 байтов.

Объединения

Особым видом структур данных является объединение. Определение объединения напоминает определение структуры, только вместо ключевого слова struct используется union:

union number {
     short sx;
     long lx;
     double dx;
};

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

struct Value {
  enum NumberType { ShortType, LongType,
                    DoubleType };
  NumberType type;  
  short sx;      // если type равен ShortType
  long lx;       // если type равен LongType
  double dx;     // если type равен DoubleType
};

Атрибут type содержит тип хранимого числа, а соответствующий атрибут структурызначение числа.

Value shortVal;
shortVal.type = Value::ShortType;
shortVal.sx = 15;

Хотя память выделяется под все три атрибута sx, lx и dx, реально используется только один из них. Сэкономить память можно, используя объединение:

struct Value {
     enum NumberType { ShortType, LongType, 
                       DoubleType };
     NumberType type;
     union number {  
          short sx;      // если type равен ShortType
          long lx;       // если type равен LongType
          double dx;     // если type равен DoubleType
     } val;
};

Теперь память выделена только для максимального из этих трех атрибутов (в данном случае dx ). Однако и обращаться с объединением надо осторожно. Поскольку все три атрибута делят одну и ту же область памяти, изменение одного из них означает изменение всех остальных. На рисунке поясняется выделение памяти под объединение. В обоих случаях мы предполагаем, что структура расположена по адресу 1000. Объединение располагает все три своих атрибута по одному и тому же адресу.

Использование памяти в объединениях.

Рис. 8.1. Использование памяти в объединениях.

Замечание. Объединения существовали в языке Си, откуда без изменений и перешли в Си++. Использование наследования классов, описанное в следующей главе, позволяет во многих случаях добиться того же эффекта без использования объединений, причем программа будет более надежной.

< Лекция 7 || Лекция 8: 1234 || Лекция 9 >
Андрей Одегов
Андрей Одегов
Язык программирования C++
Елена Шумова
Елена Шумова

Здравствуйте! Я у Вас прошла курс Язык программировая Си++.

Заказала сертификат. Хочу изменить способ оплаты. Как это сделать?