Структуры и алгоритмы компьютерной обработки данных

Объединения

Показывать лекцию целиком

Цель лекции: изучить понятия, оформления и определения объединений, доступ к элементам объединения, указатели на объединения и научиться решать задачи с использованием объединений на языке C++.

Объединение – это частный случай структуры.

Объединение подобно структуре, однако в каждый момент времени может использоваться (или, другими словами, быть ответным) только один из элементов объединения.

Объединение (смеси) – объект, который в каждый момент времени содержит один из нескольких элементов различных типов.

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

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

Определение объединений

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

Синтаксис:

union [ИмяОбъединения] { 
                        ОпределенияЭлементов; 
                       } ОбозначениеОбъединения;

где unionспецификатор типа; ИмяОбъединения – идентификатор; ОпределенияЭлементов – совокупность описаний объектов, каждый из которых служит прототипом одного из элементов объединений.

Например:

union {
       char hh[2];
       int ii;
       } CC;

Главной особенностью объединения является то, что для каждого из объявленных элементов выделяется одна и та же область памяти, т.е. они перекрываются. Хотя доступ к этой области памяти возможен с использованием любого из элементов, элемент для этой цели должен выбираться так, чтобы полученный результат не был бессмысленным.

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

Синтаксис:

typedef union [ИмяОбъединения] 
        {
         ОпределенияЭлементов; 
        } ОбозначениеОбъединения;

Например:

typedef union uni {
                   double d;
                   int i[4];
                   char ch[8];
                  } u_name;

На основе такого определения типа можно вводить конкретные объединения двумя способами:

union uni a, b;
u_name x, y;

Объединение применяется для следующих целей:

  • инициализации используемого объекта памяти, если в каждый момент времени только один объект из многих является активным;
  • интерпретации основного представления объекта одного типа, как если бы этому объекту был присвоен другой тип.
  • Доступ к элементам объединения (полям данных)

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

    ИмяОбъединения.ИмяЭлемента
    (* УказательНаОбъединение).ИмяЭлемента
    УказательНаОбъединение->ИмяЭлемента

    Например:

    СС.hh
    (*pin).mas
    pin–>mas

    Чтобы работать с объединением напрямую, надо использовать оператор "точка" (.). Если к переменной объединения обращение происходит с помощью указателя, надо использовать оператор "стрелка" ( -> ).

    Определение размера памяти, выделяемой под объединение

    Память, которая соответствует переменной типа объединение, определяется величиной для размещения любого отдельного элемента объединения.

    В отличие от структуры, объединение может в любой момент времени содержать только один из своих элементов. Объединение позволяет использовать одну область памяти для хранения различных видов данных в разные моменты времени. Фактически, объединение – это структура, в которой все поля начинаются со смещением 0, таким образом, поля накладываются друг на друга.

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

    Например:

    struct s_tag {
                  char c;
                  int i;
                  double d;
                 } s_item;
    union u_tag {
                 char c;
                 int i;
                 double d;
                } u_item;

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

    Пример 1. Определение размера структуры и объединения.

    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[]) {
      struct s_tag {
                    char c;
                    int i;
                    double d;
                   } s_item;
      union u_tag {
                   char c;
                   int i;
                   double d;
                  } u_item;
      printf("Размер структуры = %d\n", sizeof(s_item));
      printf("Размер объединения = %d\n", sizeof(u_item)); 
      system("pause");
      return 0;
    }

    Результат выполнения программы:

    Размер структуры = 16 
    Размер объединения = 8

    Например:

    union { 
           char fio[30];
           char adres[80];
           int vozrast;
           int telefon; 
          } inform;
    union {  
           int ax;
           char al[2]; 
          } ua;

    При использовании объекта inform типа union можно обрабатывать только тот элемент, который получил значение, т.е. после присвоения значения элементу inform.fio, не имеет смысла обращаться к другим элементам. Объединение ua позволяет получить отдельный доступ к младшему ua.al[0] и к старшему ua.al[1] байтам числа ua.ax.

    Использование объединений

    Допустимы массивы объединений и указатели на объединения. Объединения могут передаваться функции как параметры и возвращаться функцией.

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

    Объединение как элемент структуры

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

    Например:

    //содержит информацию о работающих служащих и пенсионерах
    struct mail {
                 char id;  // a - active (), r - retired()
                 union {
                        struct {
                                char name[30];
                                char dept[10];
                                char location[3];
                               } active;
                        struct {
                                char name[30];
                                char street[20];
                                char city_state[3];
                                char zip[5];
                               } retired;
                       } info;
                } person;

    Структура типа ). При заполнении структуры этого типа информацией в нее заносится порция данных, соответствующая элементам active или retired объединения info. Поле id устанавливается равным 'a' или 'r' для указания фактически записанного в объединении элемента. При применении объединения используется меньше памяти, чем в случае применения структуры, которая имела бы идентичные поля, но некоторые из них не использовались бы.

    (рис 17.1) Объединение как элемент структуры

    Переменные с изменяемой структурой

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

    Пример 2. Информация о геометрических фигурах представляется на основе комбинированного использования структуры и объединения.

    struct figure {
                   double area,perimetr; // общие компоненты
                   int type; // признак компонента
                   union { // перечисление компонент
                           double radius; // окружность
                           double a[2];   // прямоугольник
                           double b[3];   // треугольник
                          } geom_fig;
                  } fig1, fig2;

    В общем случае каждый объект типа figure будет состоять из трех компонентов: area, perimetr, type. Компонент type называется меткой активного компонента, так как он используется для указания, какой из компонентов объединения geom_fig является активным в данный момент. Такая структура называется переменной структурой, потому что ее компоненты меняются в зависимости от значения метки активного компонента (значение type ). Отметим, что вместо компоненты type типа int, целесообразно было бы использовать перечисляемый тип. Например, такой

    enum figure_chess {CIRCLE, BOX, TRIANGLE};

    Константы CIRCLE, BOX, TRIANGLE получат значения соответственно равные 0, 1, 2. Переменная type может быть объявлена как имеющая перечислимый тип:

    enum figure_chess type;

    В этом случае компилятор С++ предупредит программиста о потенциально ошибочных присваиваниях, таких, например, как figure.type = 40 ;

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

    struct {
            ОбщиеКомпоненты; МеткаАктивногоКомпонента;
            union { 
                   ОписаниеКомпоненты1;
                   ОписаниеКомпоненты2;
                   ...................
                   ОписаниеКомпонентыN;
                  } ИдентификаторОбъединения;
           } ИдентификаторСтруктуры;

    Пример 3. Определения переменной структуры с именем helth_record

    struct { // общая информация 
            char name[25];    // имя  
            int age;          // возраст 
            char sex;         // пол 
            // метка активного компонента(семейное положение)
            enum merital_status ins;
            // переменная часть 
            union { // холост
                    // нет компонент
                   struct { // состоит в браке 
                           char marriage_date[8];
                           char spouse_name[25];
                           int  no_children;
                          } marriage_info;
                    // разведен */
                   char date_divorced[8];
                  } marital_info;
           } health_record;
    enum marital_status { SINGLE, // холост 
                          MARRIGO, // женат 
                          DIVOREED // разведен 
                        };

    Обращаться к компонентам структуры можно при помощи ссылок:

    helth_record.nаme
      helth_record.ins
      helth_record.marriage_info.marriage_date

    Ключевые термины

    Значение указателя на объединение – это адрес расположения элементов объединения.

    Объединение (смеси) – объект, который в каждый момент времени содержит один из нескольких элементов различных типов.

    Переменные с изменяемой структурой – это переменные структурного типа, у которых компоненты меняются в зависимости от значения метки активного компонента.

    Размер объединения – это объем памяти, занимаемой объединением.

    Указатель на объединение – это указатель на расположение элементов объединения в памяти.

    Элементы объединения – это множество переменных, определяемых именем переменной объединения.

    Краткие итоги

  • Объединения являются частным случаем структур.
  • Все компоненты объявления структур применимы и при объявлении объединений.
  • Главной особенностью объединения является то, что для каждого из объявленных элементов выделяется одна и та же область памяти.
  • Доступ к элементам объединения аналогичен обращению к элементам структуры.
  • Все поля объединения располагаются по одному и тому же адресу.
  • В конкретный момент времени активным может быть только одно поле объединения.
  • Размер объединения определяется как максимальная величина длин его элементов.
  • Указатель на объединение обеспечивает доступ только к одному любому элементу объединения.
  • Структура может являться переменной, если ее компоненты меняются в зависимости от значения метки активного компонента.
  • Лабораторная работа 17. Объединения

    Цель работы: изучить понятия, оформления и определения объединений, доступ к элементам объединения, указатели на объединения и научиться решать задачи с использованием объединений на языке C++.

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

    Теоретические сведения.

    Ознакомьтесь с материалом лекции 17.

    Задания к лабораторной работе.

    Выполните приведенные ниже задания.

  • На основе определения структуры из Примера 2 лекции 17 разработайте программу, которая запрашивает параметры геометрической фигуры и выводит ее периметр и площадь.
  • На основе определения структуры из Примера 3 лекции 17 разработайте программу, которая запрашивает информацию о трех объектах и выводит ее в виде таблицы.
  • Разработайте структуру, используя объединение: Сотрудник (ФИО, пол, образование, специальность, вуз, должность, стаж). Сотрудник может не иметь высшего образования. Введите информацию о трех сотрудниках и распечатайте в виде таблицы.
  • Опишите переменную структуру для моделирования, предложенного понятия. Координаты точки (пара вещественных или комплексных чисел). Определите расстояние между двумя введенными точками.
  • Указания к выполнению работы.

    Каждое задание необходимо решить в соответствии с изученными методами объявления и обработки данных объединений в языке С++. В задачах объединение, как правило, является одним из полей структурного типа. При объявлении объединений выполните комментирование используемых полей. При выполнении задач 1 и 2 используйте Примеры 2 и 3 соответственно из материалов лекции 17. В задачах 2 и 3 следует использовать массив структур, организовав его вывод в виде таблицы.

    Следует реализовать каждое задание в соответствии с приведенными этапами:

  • изучить словесную постановку задачи, выделив при этом все виды данных;
  • сформулировать математическую постановку задачи;
  • выбрать метод решения задачи, если это необходимо;
  • разработать графическую схему алгоритма;
  • записать разработанный алгоритм на языке С++;
  • разработать контрольный тест к программе;
  • отладить программу;
  • представить отчет по работе.
  • Требования к отчету.

    Отчет по лабораторной работе должен соответствовать следующей структуре.

  • Титульный лист.
  • Словесная постановка задачи. В этом подразделе проводится полное описание задачи. Описывается суть задачи, анализ входящих в нее физических величин, область их допустимых значений, единицы их измерения, возможные ограничения, анализ условий при которых задача имеет решение (не имеет решения), анализ ожидаемых результатов.
  • Математическая модель. В этом подразделе вводятся математические описания физических величин и математическое описание их взаимодействий. Цель подраздела – представить решаемую задачу в математической формулировке.
  • Алгоритм решения задачи. В подразделе описывается разработка структуры алгоритма, обосновывается абстракция данных, задача разбивается на подзадачи. Схема алгоритма выполняется по ЕСПД (ГОСТ 19.003-80 и ГОСТ 19.002-80).
  • Листинг программы. Подраздел должен содержать текст программы на языке программирования С++, реализованный в среде MS Visual Studio 2010.
  • Контрольный тест. Подраздел содержит наборы исходных данных и полученные в ходе выполнения программы результаты.
  • Выводы по лабораторной работе.
  • Ответы на контрольные вопросы.
  • Контрольные вопросы

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