Union c что это
Перейти к содержимому

Union c что это

  • автор:

# Unions

Some C implementations permit code to write to one member of a union type then read from another in order to perform a sort of reinterpreting cast (parsing the new type as the bit representation of the old one).

It is important to note however, this is not permitted by the C standard current or past and will result in undefined behavior, none the less is is a very common extension offered by compilers (so check your compiler docs if you plan to do this).

One real life example of this technique is the "Fast Inverse Square Root" algorithm which relies on implementation details of IEEE 754 floating point numbers to perform an inverse square root more quickly than using floating point operations, this algorithm can be performed either through pointer casting (which is very dangerous and breaks the strict aliasing rule) or through a union (which is still undefined behavior but works in many compilers):

This technique was widely used in computer graphics and games in the past due to its greater speed compared to using floating point operations, and is very much a compromise, losing some accuracy and being very non portable in exchange for speed.

# Writing to one union member and reading from another

The members of a union share the same space in memory. This means that writing to one member overwrites the data in all other members and that reading from one member results in the same data as reading from all other members. However, because union members can have differing types and sizes, the data that is read can be interpreted differently, see http://stackoverflow.com/documentation/c/1119/structs-and-unions/9399/using-unions-to-reinterpret-values

The simple example below demonstrates a union with two members, both of the same type. It shows that writing to member m_1 results in the written value being read from member m_2 and writing to member m_2 results in the written value being read from member m_1 .

# Difference between struct and union

This illustrates that union members shares memory and that struct members does not share memory.

Union Types in C

Nara Bagi

Unions make us strong — except that not all unions do (at least, in the programming world).

In this article, we will explore union types in C language. We will start with a brief introduction to union types and we will move on to such important concepts, as discriminated and free unions (as well as the disadvantages of using them).

Brief Intro to Union Types

Unions are used to store different types of data in the same memory region. This saves storage space in a way similar to time-sharing the only hard copy of “Freakonomics” available in the library. Time-sharing in this case is possible if two people do not read the same hard copy at the same time. The same with unions: a union can have only one active “reader” at a given time.

Unions in C are defined in the following way, with the union statement (similar to the way struct is declared):

FreakyEconomist is the union tag. Union tags are optional — you can have anonymous unions, as well.

A variable of the type FreakyEconomist can now store members of integer, floating point type or a string of characters in the same memory space. The size of that memory space will be big enough to hold the largest member — which, in our example, is fname (100 bytes).

You can access the union members only one at a time — not all at once, as that would produce bogus results, since there’s only one memory space the members share. So, if you try the code below, meaningful results will not be printed:

Instead, something like the code snippet below can help to properly assign values to and print the values of union members (one at a time):

Members are accessed with the member access operator — a dot.

The lifetime of each union member begins when that member is activated. So, when freak.height is activated (i.e. a value is assigned to it), its lifetime begins, but the lifetime of the previously used member — freak.age — ends.

Discriminated (Tagged) Unions


It can be deduced that the usage of unions can lead to problems with type-checking. How do you guarantee that the union member currently in use is of the right type for your program to function correctly?

Enter a tag (or discriminant) — a class/field in the union data structure that explicitly indicates what type is currently active. This facilitates strong-typing (in some way) and helps to avoid unexpected errors.

So, we could re-write the previous code to be a discriminated union in this way:

Free Unions

Free unions are the exact opposite of discriminated unions — programmers have total flexibility in what types they are using for the union members. There’s freedom from type-checking. However, this is not necessarily a desired option to use as it can lead to unwanted errors, like in the code below (assuming nobody notices this mistake):

Зачем нужно объединение (union)?

уже не получится получить их назад — все перемешается? Способ сэкономить пару байтов или пару тактов и при этом сохранить читабельность? Не писать 4 разных функции, а написать одну, которая принимает union и в ней уже решать, что делать? В таком случае не проще ли принять void * и потом кастануть в тот тип, какой нужен? Как пример «Просто кастануть» приведу такой код:

Функцию принтер можно переписать как-то так:

Опять-таки какой в этом смысл, если я могу сначала завести отдельную переменную int a = 20; а затем изменю ее значение a = 50; и эффект точно такой же? Выглядит как сильное колдовство.

m9_psy's user avatar

Union-ы (объединения) используют в двух случаях:

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

Один из примеров подобного применения в реальной жизни — структура VARIANT из Windows API.

Иными словами, это предшественник современных boost::variant , QVariant и т. д. Однако вышеперечисленные классы могут хранить в себе непримитивные типы (с конструкторами, деструкторами и операторами копирования), а union — нет.

Для преобразования между несовместимыми типами. Традиционно для этих целей используют оператор преобразования (T) , либо reinterpret_cast<> . Однако эти способы опасны нарушением strict aliasing rule и, как результат, порождением неопределённого (то есть непредсказуемого) поведения.

Правильные способы преобразования — это либо memcpy (подобный вызов которого выбрасывается компилятором), либо использование union -а.

UPD: Внимание! Преобразование через union является допустимым только в Си, но не в C++. В ответе на вопрос «Accessing inactive union member and undefined behavior?» приводятся отсылки на следующие пункты стандартов: Структуры и члены объединений

95) Если поле, используемое для чтения содержимого объекта-объединения, не является полем, использованным ранее для записи значения в этот объект, требуемая часть внутреннего представления объекта интерпретируется в соответствием с представлением затребованного типа согласно 6.2.6 (данный процесс известен также как type punning). Это представление может приводить к неопределённому поведению. Structure and union members

95) If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type punning’’). This might be a trap representation.

C Union – Syntax and Examples

C unions are used to save memory. To better understand an union, think of it as a chunk of memory that is used to store variables of different types. When we want to assign a new value to a field, then the existing data is replaced with new data.

C unions allow data members which are mutually exclusive to share the same memory. This is quite important when memory is valuable, such as in embedded systems. Unions are mostly used in embedded programming where direct access to the memory is needed.

Difference between structure and union

The main difference between structure and a union is that

  • Structs allocate enough space to store all of the fields in the struct. The first one is stored at the beginning of the struct, the second is stored after that, and so on.
  • Unions only allocate enough space to store the largest field listed, and all fields are stored at the same space .

Syntax for Declaring a C union

Syntax for declaring a union is same as that of declaring a structure except the keyword struct.

Note : Size of the union is the the size of its largest field because sufficient number of bytes must be reserved to store the largest sized field.

To access the fields of a union, use dot(.) operator i.e., the variable name followed by dot operator followed by field name.

Initializing unions

The difference between structure and union when their initialization is given below.

C Program


The fields of a union cannot be initialized all at once. For a structure variable the output is fine but for the union variable the answer does not seem to be correct because union can hold single value for a member at a time i.e., the data is over-written in the memory. Obviously the use case we have chosen is not suited for union but only struct. This example is only to demonstrate the behavior of union and structure.

Unions inside structure

In the below code, we have union embedded with in a structure. We know, the fields of a union will share memory, so in main program we ask the user which data he/she would like to store and depending on the user choice the appropriate field will be used. By this way we can use the memory efficiently.

C Program


Structures inside Unions

Example for defining a structure inside union is given below.

C Program


In this C Tutorial, we have learnt about C unions, their syntax and usage. Also, we learnt how C unions are different from C structures.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *