Тип союза - Union type

В Информатика, а союз это ценить которые могут иметь любое из нескольких представлений или форматов в одной позиции в объем памяти; который состоит из Переменная что может провести такой структура данных. Немного языки программирования поддержка специальных типы данных, называется типы профсоюзов, чтобы описать такие значения и переменные. Другими словами, определение типа объединения будет указывать, какой из ряда разрешенных типов примитивов может храниться в его экземплярах, например, «с плавающей запятой или длинное целое число». В отличие от записывать (или структура), которая может содержать поплавок и целое число; в объединении в любой момент времени может быть только одно значение.

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

В теория типов, у союза есть тип суммы; это соответствует несвязный союз по математике.

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

Без тегов союзы

Из-за ограничений в использовании немаркированные объединения обычно предоставляются только на нетипизированных языках или небезопасным для типов способом (как в C ). У них есть преимущество перед простыми помеченными объединениями в том, что они не требуют места для хранения тега типа данных.

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

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

Союзы на разных языках программирования

АЛГОЛ 68

АЛГОЛ 68 имеет теги союзов и использует предложение case, чтобы различать и извлекать составляющий тип во время выполнения. Объединение, содержащее другое объединение, рассматривается как набор всех составляющих его возможностей.

Синтаксис типа объединения C / C ++ и понятие приведения типов были унаследованы от АЛГОЛА 68, хотя и в немаркированной форме.[1]

C / C ++

В C и C ++, немаркированные объединения выражаются почти так же, как структуры (структуры ), за исключением того, что каждый элемент данных начинается в одном месте в памяти. Члены данных, как и в структурах, не обязательно должны быть примитивными значениями и фактически могут быть структурами или даже другими объединениями. C ++ (поскольку C ++ 11 ) также позволяет члену данных быть любым типом, который имеет полноценный конструктор / деструктор и / или конструктор копирования, или нетривиальный оператор присваивания копии. Например, можно иметь стандартный C ++ нить как член профсоюза.

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

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

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

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

— ANSI / ISO 9899: 1990 (стандарт ANSI C), раздел 6.5.2.1

Анонимный союз

В C ++ C11, и как нестандартное расширение во многих компиляторах, объединения также могут быть анонимными. На их элементы данных не нужно ссылаться, вместо этого доступ осуществляется напрямую. У них есть некоторые ограничения в отличие от традиционных союзов: в C11 они должны быть членами другой структуры или союза,[2] а в C ++ они не могут иметь методы или спецификаторы доступа.

Простое исключение части синтаксиса имени класса не делает объединение анонимным. Чтобы объединение считалось анонимным объединением, объявление не должно объявлять объект. Пример:

#включают <iostream>#включают <cstdint>int главный() {   с помощью пространство имен стандартное;   союз {      плавать ж;      uint32_t d; // Предполагается, что число с плавающей запятой имеет ширину 32 бита   };   ж = 3.14f;   cout << "Двоичное представление 3.14 =" << шестнадцатеричный << d << конец;   возвращаться 0;}

Прозрачный союз

В Unix-подобных компиляторах, таких как GCC, Clang и IBM XL C для AIX, transparent_union атрибут доступен для типов объединения. Типы, содержащиеся в объединении, могут быть прозрачно преобразованы в сам тип объединения при вызове функции при условии, что все типы имеют одинаковый размер. Он в основном предназначен для работы с интерфейсами с несколькими параметрами, использование которых необходимо для ранних расширений Unix и последующей повторной стандартизации.[3]

КОБОЛ

В КОБОЛ, элементы данных объединения определяются двумя способами. Первый использует ПЕРЕИМЕНОВАТЬ (66 level) ключевое слово, которое эффективно отображает второй буквенно-цифровой элемент данных поверх той же ячейки памяти, что и предыдущий элемент данных. В приведенном ниже примере кода элемент данных PERSON-REC определяется как группа, содержащая другую группу и числовой элемент данных. ЛИЧНЫЕ ДАННЫЕ определяется как буквенно-цифровой элемент данных, который переименовывает PERSON-REC, обрабатывая байты данных, продолженные в нем, как символьные данные.

  01  PERSON-REC.05  ЛИЦО.    10  ЛИЦО-ИМЯ-ПОСЛЕДНИЙ    ПИК X (12).    10  ПЕРВЫЙ ЛИЦО   ПИК X (16).    10  ЛИЦО-ИМЯ-МИД     PIC X.05  PERSON-ID               ПИК 9 (9) УПАКОВАННЫЙ-ДЕСЯТИЧНЫЙ.    01  ЛИЧНЫЕ ДАННЫЕ                 ПЕРЕИМЕНОВАТЬ PERSON-REC.

Второй способ определить тип объединения - использовать ПОВТОРЯЕТ ключевое слово. В приведенном ниже примере кода элемент данных VERS-NUM определяется как 2-байтовое двоичное целое число, содержащее номер версии. Второй элемент данных VERS-BYTES определяется как двухсимвольная буквенно-цифровая переменная. Поскольку второй элемент переопределенный по первому элементу два элемента имеют один и тот же адрес в памяти и, следовательно, используют одни и те же базовые байты данных. Первый элемент интерпретирует два байта данных как двоичное значение, а второй элемент интерпретирует байты как символьные значения.

  01  VERS-INFO.05  VERS-NUM        ПИК S9 (4) КОМП.05  VERS-BYTES      ПИК X (2) ПОВТОРЯЕТ VERS-NUM

PL / I

В PL / I тогда первоначальный термин для союза был ячейка,[4] который до сих пор принимается некоторыми компиляторами как синоним объединения. Объявление union аналогично определению структуры, где элементы на одном уровне в объявлении union занимают одно и то же хранилище. Элементы объединения могут быть любого типа данных, включая структуры и массивы.[5]:pp192–193 Здесь vers_num и vers_bytes занимают одни и те же места хранения.

  1  vers_info         союз,     5 vers_num        фиксированный двоичный,     5 vers_bytes      pic '(2) A';

Альтернативой объявлению объединения является атрибут DEFINED, который допускает альтернативные объявления хранилища, однако типы данных базовой и определенной переменных должны совпадать.[5]:стр.289–293

Синтаксис и пример

В C и C ++ синтаксис:

союз <имя>{    <тип данных>  <1ул Переменная имя>;    <тип данных>  <2nd Переменная имя>;    .    .    .    <тип данных>  <nth Переменная имя>;} <союз Переменная имя>;

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

союз name1{    структура имя2    {          int     а;        плавать   б;        char    c;    } свар;    int     d;} увар;

В этом примере определяется переменная увар как союз (помечен как name1), который содержит два члена, структуру (помеченную как имя2) названный свар (который, в свою очередь, содержит три члена) и целочисленную переменную с именем d.

Объединения могут происходить внутри структур и массивов, и наоборот:

структура{      int флаги;    char *имя;    int utype;    союз {        int ival;        плавать fval;        char *сваль;    } ты;} symtab[NSYM];

Число ival упоминается как symtab [i] .u.ival, а первый символ строки sval - через * symtab [i] .u.sval или symtab [i] .u.sval [0].

PHP

Типы объединения были представлены в PHP 8.0.[6]

учебный класс Пример{    частный int|плавать $ foo;    общественный функция squareAndAdd(плавать|int $ бар): int|плавать    {        возвращаться $ бар ** 2 + $ foo;    }}

Машинопись

Типы объединения поддерживаются в TypeScript.[7]

функция квадрат(бар: плавать | int): int | плавать {    возвращаться бар ** 2;}

Разница между союзом и структурой

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

В структуре все ее элементы данных хранятся в непрерывных ячейках памяти. Таким образом, размер объекта структуры - это размер суммы всех ее элементов данных.

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

В качестве примера, иллюстрирующего этот момент, объявление

структура фу { int а; плавать б; }

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

                ┌─────┬─────┐ foo │ a │ b │ └─────┴─────┘ ↑ ↑ Адрес памяти: 0150 0154

Напротив, декларация

союз бар { int а; плавать б; }

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

                ┌─────┐ bar │ a │ │ b │ └─────┘ ↑ Адрес памяти: 0150

Структуры используются там, где «объект» состоит из других объектов, например, точечный объект, состоящий из двух целых чисел, которые являются координатами x и y:

typedef структура {    int Икс;           // x и y разделены    int у;} tPoint;

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

typedef перечислить { STR, INT } tType;typedef структура {    tType тип;          // тип отдельный.    союз {        int ival;       // ival и sval занимают одну и ту же память.        char *сваль;    };} tVal;

Смотрите также

Рекомендации

  1. ^ Ричи, Деннис М. (Март 1993 г.). «Развитие языка Си». Уведомления ACM SIGPLAN. 28 (3): 201–208. Дои:10.1145/155360.155580. Схема набора шрифтов, принятая в Си, в значительной степени обязана Алголу 68, хотя, возможно, она не возникла в той форме, которую одобрили бы приверженцы Алгола. Центральным понятием, которое я уловил из Алгола, была структура типов, основанная на атомарных типах (включая структуры), составленных в массивы, указатели (ссылки) и функции (процедуры). Концепция объединений и приведений в Алголе 68 также оказала влияние, появившееся позже.CS1 maint: ref = harv (ссылка на сайт)
  2. ^ «6.63 Безымянная структура и поля объединения». Получено 2016-12-29.
  3. ^ «Атрибуты общего типа: transparent_union». Использование коллекции компиляторов GNU (GCC).
  4. ^ Корпорация IBM (март 1968 г.). Спецификации языка IBM System / 360 PL / I (PDF). п. 52. Получено 22 янв, 2018.
  5. ^ а б Корпорация IBM (декабрь 2017 г.). Enterprise PL / I для z / OS PL / I для AIX IBM Developer для z Systems PL / I для Windows Справочник по языку (PDF). Получено 22 янв, 2018.
  6. ^ Карунаратне, Аиш. «PHP 8.0: типы объединения». PHP.Watch. Получено 30 ноября 2020.
  7. ^ «Справочник - Союзы и типы пересечений». www.typescriptlang.org. Получено 30 ноября 2020.

внешняя ссылка