Тип объединения

редактировать

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

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

В теории типов объединение имеет тип суммы ; это соответствует непересекающемуся объединению в математике.

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

Содержание

  • 1 Без тегов
  • 2 Союзы на разных языках программирования
    • 2.1 АЛГОЛ 68
    • 2.2 C / C ++
      • 2.2.1 Анонимное объединение
      • 2.2.2 Прозрачное объединение
    • 2.3 COBOL
    • 2.4 PL / I
  • 3 Синтаксис и пример
  • 4 Разница между объединением и структурой
  • 5 См. Также
  • 6 Ссылки
  • 7 Внешние ссылки

Объединения без тегов

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

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

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

Объединения в различные языки программирования

АЛГОЛ 68

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

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

C / C ++

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

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

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

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

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

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

Анонимное объединение

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

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

#include #include int main () {using namespace std; союз {float f; uint32_t d; // Предполагается, что число с плавающей запятой имеет ширину 32 бита}; f = 3,14f; cout << "Binary representation of 3.14 = " << hex << d << endl; return 0; }

Прозрачное объединение

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

COBOL

В COBOL элементы данных объединения являются определяется двумя способами. Первый использует ключевое слово RENAMES(уровень 66), которое эффективно отображает второй буквенно-цифровой элемент данных поверх той же области памяти, что и предыдущий элемент данных. В приведенном ниже примере кода элемент данных PERSON-RECопределен как группа, содержащая другую группу и элемент числовых данных. PERSON-DATAопределяется как буквенно-цифровой элемент данных, который переименовывает PERSON-REC, обрабатывая байты данных, продолжающиеся в нем, как символьные данные.

01 ЛИЧНАЯ-ЗАП. 05 ИМЯ. 10 ИМЯ-ЛИЦО-ПОСЛЕДНИЙ ФОТО X (12). 10 ПЕРВОЕ ИМЯ ФОТО X (16). 10 PERSON-NAME-MID PIC X. 05 PERSON-ID PIC 9 (9) PACKED-DECIMAL. 01 PERSON-DATA ПЕРЕИМЕНОВАТЬ PERSON-REC.

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

01 СТИХ-ИНФ. 05 НОМЕР ВЕРСЫ PIC S9 (4) КОМП. 05 VERS-BYTES PIC X (2) REDEFINES VERS-NUM

PL / I

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

1 объединение Vers_info, 5 фиксированных двоичных номеров Vers_num, 5 байтов Vers_bytes pic '(2) A';

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

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

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

union { <1st variable name>; <2nd variable name>;... ; } ;

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

union name1 {struct name2 {int a; float b; char c; } свар; int d; } увар;

В этом примере переменная uvarопределяется как объединение (с тегом name1), которое содержит два члена, структуру (с тегом name2) с именем svar(который, в свою очередь, содержит три члена) и целочисленная переменная с именем d.

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

struct {int flags; название символа; int utype; союз {int ival; float fval; char * sval; } u; } symtab [NSYM];

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

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

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

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

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

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

struct foo {int a; float b; }

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

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

Напротив, объявление

union bar {int a; float b; }

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

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

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

typedef struct {int x; // x и y разделены int y; } tPoint;

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

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

См. Также

Ссылки

Внешние ссылки

Последняя правка сделана 2021-06-20 11:21:36
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте