C Language
Союзы
Поиск…
Разница между структурой и объединением
Это иллюстрирует, что члены профсоюза разделяют память и члены структуры не обмениваются памятью.
#include <stdio.h>
#include <string.h>
union My_Union
{
int variable_1;
int variable_2;
};
struct My_Struct
{
int variable_1;
int variable_2;
};
int main (void)
{
union My_Union u;
struct My_Struct s;
u.variable_1 = 1;
u.variable_2 = 2;
s.variable_1 = 1;
s.variable_2 = 2;
printf ("u.variable_1: %i\n", u.variable_1);
printf ("u.variable_2: %i\n", u.variable_2);
printf ("s.variable_1: %i\n", s.variable_1);
printf ("s.variable_2: %i\n", s.variable_2);
printf ("sizeof (union My_Union): %i\n", sizeof (union My_Union));
printf ("sizeof (struct My_Struct): %i\n", sizeof (struct My_Struct));
return 0;
}
Использование союзов для повторной интерпретации значений
Некоторые реализации C позволяют коду писать одному члену типа объединения, а затем читать от другого, чтобы выполнить своего рода реинтерпретацию (разбор нового типа в виде битового представления старого).
Однако важно отметить, что это не разрешено стандартным током C или прошлым и приведет к неопределенному поведению, тем не менее, это очень распространенное расширение, предлагаемое компиляторами (так что проверьте свои документы компилятора, если вы планируете это делать) ,
Одним из реальных примеров этого метода является алгоритм «Быстрый обратный квадратный корень», который опирается на детали реализации чисел с плавающей запятой IEEE 754 для выполнения обратного квадратного корня быстрее, чем при использовании операций с плавающей запятой, этот алгоритм может выполняться либо путем кастования указателя (что очень опасно и нарушает правило строгого псевдонима) или через объединение (которое по-прежнему является неопределенным поведением, но работает во многих компиляторах):
union floatToInt
{
int32_t intMember;
float floatMember; /* Float must be 32 bits IEEE 754 for this to work */
};
float inverseSquareRoot(float input)
{
union floatToInt x;
int32_t i;
float f;
x.floatMember = input; /* Assign to the float member */
i = x.intMember; /* Read back from the integer member */
i = 0x5f3759df - (i >> 1);
x.intMember = i; /* Assign to the integer member */
f = x.floatMember; /* Read back from the float member */
f = f * (1.5f - input * 0.5f * f * f);
return f * (1.5f - input * 0.5f * f * f);
}
Этот метод широко использовался в компьютерной графике и играх в прошлом из-за его большей скорости по сравнению с использованием операций с плавающей запятой и является очень компромиссным, теряя определенную точность и очень не переносимый в обмен на скорость.
Запись одному члену профсоюза и чтение от другого
Члены профсоюза имеют одинаковое пространство в памяти. Это означает, что запись в один член перезаписывает данные во всех других членах и что чтение из одного члена приводит к тем же данным, что и чтение от всех других членов. Однако, поскольку члены профсоюза могут иметь разные типы и размеры, данные, которые читаются, могут интерпретироваться по-разному, см. Http://www.riptutorial.com/c/example/9399/using-unions-to-reinterpret-values
Простой пример ниже демонстрирует объединение с двумя членами, одинаковыми типами. Он показывает, что запись в член m_1
приводит к тому, что записанное значение считывается из члена m_2
а запись в член m_2
приводит к тому, что записанное значение считывается из члена m_1
.
#include <stdio.h>
union my_union /* Define union */
{
int m_1;
int m_2;
};
int main (void)
{
union my_union u; /* Declare union */
u.m_1 = 1; /* Write to m_1 */
printf("u.m_2: %i\n", u.m_2); /* Read from m_2 */
u.m_2 = 2; /* Write to m_2 */
printf("u.m_1: %i\n", u.m_1); /* Read from m_1 */
return 0;
}
Результат
u.m_2: 1
u.m_1: 2