Поиск…


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

Это иллюстрирует, что члены профсоюза разделяют память и члены структуры не обмениваются памятью.

#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


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow