Zoeken…


Verschil tussen struct en unie

Dit illustreert dat vakbondsleden geheugen delen en dat struct-leden geen geheugen delen.

#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;
}

Vakbonden gebruiken om waarden opnieuw te interpreteren

Sommige C-implementaties staan code toe om naar een lid van een unietype te schrijven en vervolgens van een ander lid te lezen om een soort herinterpretatie-cast uit te voeren (het nieuwe type parseren als de bitrepresentatie van het oude).

Het is echter belangrijk op te merken dat dit niet is toegestaan door de C-standaard huidig of in het verleden en zal resulteren in ongedefinieerd gedrag. Dit is echter een veel voorkomende extensie die wordt aangeboden door compilers (controleer dus uw compilerdocumenten als u van plan bent dit te doen) .

Een echt voorbeeld van deze techniek is het "Fast Inverse Square Root" -algoritme dat afhankelijk is van implementatiedetails van IEEE 754-floating point-nummers om sneller een inverse vierkantswortel uit te voeren dan drijvende-kommabewerkingen. Dit algoritme kan worden uitgevoerd via pointer casting (wat erg gevaarlijk is en de strikte aliasregel overtreedt) of via een unie (wat nog steeds ongedefinieerd gedrag is maar in veel compilers werkt):

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);
}

Deze techniek werd in het verleden veel gebruikt in computergraphics en games vanwege de hogere snelheid vergeleken met drijvende-kommabewerkingen, en is een compromis, verliest enige nauwkeurigheid en is niet draagbaar in ruil voor snelheid.

Schrijven naar het ene vakbondslid en lezen van het andere

De leden van een vakbond delen dezelfde ruimte in het geheugen. Dit betekent dat schrijven naar één lid de gegevens in alle andere leden overschrijft en dat lezen van één lid dezelfde gegevens oplevert als lezen van alle andere leden. Omdat vakbondsleden verschillende typen en groottes kunnen hebben, kunnen de gelezen gegevens anders worden geïnterpreteerd, zie http://www.riptutorial.com/c/example/9399/using-unions-to-reinterpret-values

Het eenvoudige voorbeeld hieronder toont een unie met twee leden, beide van hetzelfde type. Het laat zien dat schrijven naar lid m_1 resulteert in het lezen van de geschreven waarde van lid m_2 en schrijven naar lid m_2 resulteert in het lezen van de geschreven waarde van lid 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;
}

Resultaat

u.m_2: 1
u.m_1: 2


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow