1.Описание языка СИ.

1.2.Типы данных и их объявление.

Объединения (смеси).

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

 
     union {   описание элемента 1;
               ...
               описание элемента n; };
 

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

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

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

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

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

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

Пример:

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

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

1.2.9. Поля битов

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

 
     struct { unsigned идентификатор 1 :  длина-поля  1;
              unsigned идентификатор 2 :  длина-поля  2;    }
 

длинна - поля задается целым выражением или константой. Эта константа определяет число битов, отведенное соответствующему полю. Поле нулевой длинны обозначает выравнивание на границу следующего слова.

Пример:

 
      struct { unsigned a1 :  1;
               unsigned a2 :  2;
               unsigned a3 :  5;
               unsigned a4 :  2;  } prim;
 

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

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

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

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

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

 
       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 ;
                        } идентификатор-объединения ;
             } идентификатор-структуры ;
 

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

 
     struct { /* общая информация */
               char  name [25];   /* имя       */
               int   age;         /* возраст   */
               char  sex;         /* пол       */
               /*   метка   активного   компонента  */
               /*   (семейное положение)            */
               enum merital_status ins;
               /* переменная часть */
               union  {   /* холост        */
                          /* нет компонент */
                        struct {  /* состоит в браке */
                                 char marripge_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.neme,
  helth_record.ins,
  helth_record.marriage_info.marriage_date .