C: gdzie Unia jest praktycznie używana?

Mam ze sobą przykład, w którym zagwarantowane jest wyrównanie typu, union max_align . Szukam jeszcze prostszego przykładu, w którym związek jest używany praktycznie, aby wyjaśnić mojego przyjaciela.

 30
Author: timrau, 2009-12-23

18 answers

Zwykle używam związków podczas parsowania tekstu. Używam czegoś takiego:

typedef enum DataType { INTEGER, FLOAT_POINT, STRING } DataType ;

typedef union DataValue
{
    int v_int;
    float v_float;
    char* v_string;
}DataValue;

typedef struct DataNode
{
    DataType type;
    DataValue value;
}DataNode;

void myfunct()
{
    long long temp;
    DataNode inputData;

    inputData.type= read_some_input(&temp);

    switch(inputData.type)
    {
        case INTEGER: inputData.value.v_int = (int)temp; break;
        case FLOAT_POINT: inputData.value.v_float = (float)temp; break;
        case STRING: inputData.value.v_string = (char*)temp; break;
    }
}

void printDataNode(DataNode* ptr)
{
   printf("I am a ");
   switch(ptr->type){
       case INTEGER: printf("Integer with value %d", ptr->value.v_int); break;
       case FLOAT_POINT: printf("Float with value %f", ptr->value.v_float); break;
       case STRING: printf("String with value %s", ptr->value.v_string); break;
   }
}

Jeśli chcesz zobaczyć, jak często używane są związki, sprawdź dowolny kod używając flex/Bizon . Na przykład patrz splint , zawiera mnóstwo związków.

 33
Author: Yousf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-20 13:11:20

Zazwyczaj używam związków, w których chcesz mieć różne poglądy na dane np. 32-bitowa wartość koloru, w której potrzebne są zarówno 32-bitowe wartości val,jak i Komponenty red,green, blue I alpha

struct rgba
{
  unsigned char r;
  unsigned char g;
  unsigned char b;
  unsigned char a;
};

union  
{
  unsigned int val;
  rgba components;
}colorval32;

NB można również osiągnąć to samo z bit-maskowanie i przesunięcie TJ

#define GETR(val) ((val&0xFF000000) >> 24)

Ale uważam, że podejście Unii jest bardziej eleganckie

 6
Author: zebrabox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:34:16

Aby uzyskać dostęp do rejestrów lub portów we/wy zarówno bajtowo, jak i bitowo poprzez mapowanie danego portu do pamięci, zobacz poniższy przykład:

    typedef Union
{
  unsigned int a;
struct {
  unsigned bit0 : 1,
           bit1 : 1,
           bit2 : 1,
           bit3 : 1,
           bit4 : 1,
           bit5 : 1,
           bit6 : 1,
           bit7 : 1,
           bit8 : 1,
           bit9 : 1,
           bit10 : 1,
           bit11 : 1,
           bit12 : 1,
           bit13 : 1,
           bit14 : 1,
           bit15 : 1
} bits;
} IOREG;

# define PORTA (*(IOREG *) 0x3B)
...
unsigned int i = PORTA.a;//read bytewise
int j = PORTA.bits.bit0;//read bitwise
...
PORTA.bits.bit0 = 1;//write operation
 5
Author: wrapperm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:33:17

W świecie Windows, unionssą powszechnie używane do implementacji oznaczonych wariantów, które są (lub były, przed.NET?) jednym ze standardowych sposobów przekazywania danych pomiędzy obiektami COM.

Chodzi o to, że typ union może zapewnić pojedynczy naturalny interfejs do przesyłania dowolnych danych między dwoma obiektami. Jakiś obiekt COM może przekazać Ci wariant (np. typ VARIANT lub _variant_t) które mogą zawierać albo double, float, int, albo cokolwiek.

Jeśli masz aby poradzić sobie z obiektami COM w kodzie Windows C++, zobaczysz typy wariantów wszędzie.

 3
Author: Nate Kohl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-24 13:41:37
struct cat_info
{
int legs;
int tailLen;
};

struct fish_info
{
bool hasSpikes;
};


union 
{
fish_info fish;
cat_info cat;
} animal_data;

struct animal
{
char* name;
int animal_type;
animal_data data;
};
 2
Author: ironic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:17:24

Związki są przydatne, jeśli masz różne rodzaje wiadomości, w takim przypadku nie musisz znać na żadnym poziomie pośrednim dokładnego typu. Tylko nadawca i odbiorca muszą analizować aktualną wiadomość. Wszelkie inne poziomy tylko naprawdę muszą znać rozmiar i ewentualnie informacje o nadawcy i / lub odbiorcy.

 2
Author: Makis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:58:34

SDL używa Unii do reprezentowania zdarzeń: http://www.libsdl.org/cgi/docwiki.cgi/SDL_Event .

 2
Author: Bastien Léonard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 18:25:00

Masz na myśli coś takiego ?

union {
   long long a;
   unsigned char b[sizeof(long long)];
} long_long_to_single_bytes;

Dodano :

Ostatnio użyłem tego na naszej maszynie AIX, aby przekształcić 64-bitowy identyfikator maszyny W tablicę bajtów.

std::string getHardwareUUID(void) {
#ifdef AIX
   struct xutsname m; // aix specific struct to hold the 64bit machine id
   unamex(&b);        // aix specific call to get the 64bit machine id
   long_long_to_single_bytes.a = m.longnid;
   return convertToHexString(long_long_to_single_bytes.b, sizeof(long long));
#else // Windows or Linux or Solaris or ...
   ... get a 6byte ethernet MAC address somehow and put it into mac_buf
   return convertToHexString(mac_buf, 6);
#endif
 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 18:01:03

Oto kolejny przykład, w którym Unia może być przydatna.

(nie mój własny pomysł, znalazłem to na dokumencie omawiającym C++ optymalizacje)

Begin-quote

.... Związki mogą być również używane do oszczędzania miejsca, np.

Najpierw podejście pozaunijne:

void F3(bool useInt) {
    if (y) {
        int a[1000];
        F1(a);  // call a function which expects an array of int as parameter
    }
    else {
        float b[1000];
        F2(b);  // call a function which expects an array of float as parameter
    }
}

Tutaj można użyć tego samego obszaru pamięci dla a i b, ponieważ ich zakresy na żywo tak nie pokrywają się. Możesz zaoszczędzić dużo miejsca cpu-cache łącząc a i b W a "Unia": {]}

void F3(bool useInt) {

    union {
        int a[1000];
        float b[1000];
    };

    if (y) {
        F1(a);  // call a function which expects an array of int as parameter
    }
    else {
        F2(b);  // call a function which expects an array of float as parameter
    }
}

Używanie Unii nie jest oczywiście bezpieczną praktyką programowania, ponieważ nie Ostrzeżenie ze strony kompilatora, jeśli zastosowania a i b nakładają się na siebie. Należy używać tylko tej metody dla dużych obiektów, które zajmują dużo miejsca w pamięci podręcznej. ...

End-qoute

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 19:30:34

Używałem czasem związków w ten sposób

//Define type of structure
typedef enum { ANALOG, BOOLEAN, UNKNOWN } typeValue_t;
//Define the union
typedef struct  {
  typeValue_t typeValue;
  /*On this structure you will access the correct type of
    data according to its type*/
  union {
    float ParamAnalog;
    char  ParamBool;
  };
} Value_t;

Następnie można zadeklarować tablice różnego rodzaju wartości, przechowując mniej lub bardziej efektywnie Dane i wykonać kilka operacji "polimorph", takich jak:

 void printValue ( Value_t value ) {
    switch (value.typeValue) {
       case BOOL:
          printf("Bolean: %c\n", value.ParamBool?'T':'F');
          break;
       case ANALOG:
          printf("Analog: %f\n", value.ParamAnalog);
          break;
       case UNKNOWN:
          printf("Error, value UNKNOWN\n");
          break;
    }
 }
 1
Author: Khelben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 23:59:12
  • podczas odczytu danych serializowanych, które muszą być przypisane do określonych typów.
  • zwracając wartości semantyczne z lex do yacc. (yylval)
  • przy implementacji typu polimorficznego, zwłaszcza takiego, który czyta DSL lub ogólny język
  • podczas implementacji dyspozytora, który w szczególności wywołuje funkcje przeznaczone do przyjmowania różnych typów.
 1
Author: DigitalRoss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-24 17:19:55

Ostatnio chyba widziałem jakiś związek używany w programowaniu wektorowym . programowanie wektorowe jest używane w technologii intel MMX , sprzęcie GPU, komórkowym silniku szerokopasmowym IBM i innych.

Wektor może odpowiadać rejestrowi 128-bitowemu. Jest bardzo powszechnie stosowany w architekturze SIMD. ponieważ sprzęt posiada 128-bitowe rejestry, w rejestrze/zmiennej można przechowywać 4 punkty zmiennoprzecinkowe o pojedynczej precyzji. łatwy sposób konstruowania, konwertowania, wyodrębniania poszczególnych elementami wektora jest użycie związku.

typedef union {
    vector4f vec; // processor-specific built-in type
    struct { // human-friendly access for transformations, etc
        float x;
        float y;
        float z;
        float w;
    };
    struct { // human-friendly access for color processing, lighting, etc
        float r;
        float g;
        float b;
        float a;
    };
    float arr[4]; // yet another convenience access
} Vector4f;

int main()
{
    Vector4f position, normal, color;
    // human-friendly access
    position.x = 12.3f;
    position.y = 2.f;
    position.z = 3.f;
    position.w = 1.f;

    // computer friendly access
    //some_processor_specific_operation(position.vec,normal.vec,color.vec);
    return 0;
}

Jeśli podążasz ścieżką programowania wielordzeniowego PlayStation 3 lub programowania grafiki, jest duża szansa, że napotkasz więcej takich rzeczy.

 1
Author: Afriza N. Arief,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 18:45:15

Wiem, że jestem trochę spóźniony na imprezę, ale jako praktyczny przykład typ danych Variant w Vbscripcie jest, jak sądzę, zaimplementowany jako Union. Poniższy kod jest uproszczonym przykładem zaczerpniętym z artykułu znalezionego tutaj

struct tagVARIANT
{
    union 
    {
        VARTYPE vt;
        WORD wReserved1;
        WORD wReserved2;
        WORD wReserved3;
        union 
        {
            LONG lVal;
            BYTE bVal;
            SHORT iVal;
            FLOAT fltVal;
            DOUBLE dblVal;
            VARIANT_BOOL boolVal;
            DATE date;
            BSTR bstrVal;
            SAFEARRAY *parray;
            VARIANT *pvarVal;
        };
    };
};

Rzeczywista implementacja (jak stwierdza artykuł) znajduje się w oaidl.h c plik nagłówkowy.

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-25 13:04:03

Przykład:

Podczas używania różnych typów gniazd, ale chcesz, aby Typ comon się odnosił.

 0
Author: Xolve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:00:47

Kolejny przykład więcej: aby zapisać robi odlewy.

typedef union {
  long int_v;
  float float_v;
} int_float;

void foo(float v) {
  int_float i;
  i.float_v = v;
  printf("sign=%d exp=%d fraction=%d", (i.int_v>>31)&1, ((i.int_v>>22)&0xff)-128, i.int_v&((1<<22)-1));
}

Zamiast:

void foo(float v) {
  long i = *((long*)&v);
  printf("sign=%d exp=%d fraction=%d", (i>>31)&1, ((i>>22)&0xff)-128, i&((1<<22)-1));
}
 0
Author: fortran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:30:45

Dla wygody używam unions, aby pozwolić mi używać tej samej klasy do przechowywania wartości xyzw i RGBA

#ifndef VERTEX4DH
    #define VERTEX4DH

    struct Vertex4d{

        union {
            double x;
            double r;
        };
        union {
            double y;
            double g;
        };
        union {
            double z;
            double b;
        };
        union {
            double w;
            double a;
        };

        Vertex4d(double x=0, double y=0,double z=0,double w=0) : x(x), y(y),z(z),w(w){}
    };

#endif
 0
Author: Tom J Nowell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 08:40:26

Wiele przykładów związków można znaleźć w <X11/Xlib.h>. Kilka innych znajduje się w niektórych stosach IP (na przykład w BSD <netinet/ip.h>).

Z reguły implementacje protokołu używają konstrukcji Unii.

 0
Author: mouviciel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 09:26:53

Związki mogą być również użyteczne, gdy typują , co jest pożądane w kilku wybranych miejscach(np. niektóre techniki algorytmów porównywania zmiennoprzecinkowego ).

 0
Author: fbrereto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-23 19:59:13