C: Где практически используется соединение? - PullRequest
30 голосов
/ 23 декабря 2009

У меня есть пример, в котором гарантируется выравнивание типа union max_align. Я ищу еще более простой пример, в котором объединение используется практически, чтобы объяснить моему другу.

Ответы [ 18 ]

33 голосов
/ 23 декабря 2009

Я обычно использую союзы при разборе текста. Я использую что-то вроде этого:

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

Если вы хотите увидеть, как профсоюзы используются в тяжелом режиме, проверьте любой код, используя flex / bison . Например, см. splint , он содержит ТОННЫ союзов.

6 голосов
/ 23 декабря 2009

Я обычно использовал союзы, где вы хотите иметь разные представления данных например 32-битное значение цвета, в котором необходимо указать 32-битное значение val, а также красный, зеленый, синий и альфа-компоненты

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

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

NB. Вы также можете добиться того же с помощью маскировки битов и сдвига, т.е.

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

, но я считаю, что профсоюзный подход более элегантен

5 голосов
/ 23 декабря 2009

Для доступа к регистрам или портам ввода-вывода как побитовым, так и побитовым путем привязки этого конкретного порта к памяти, см. Пример ниже:

    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
3 голосов
/ 23 декабря 2009

В мире Windows unions обычно используются для реализации теговых вариантов , которые являются (или были до .NET?) Одним стандартным способом передачи данных между COM-объектами .

Идея состоит в том, что тип union может обеспечить единый естественный интерфейс для передачи произвольных данных между двумя объектами. Некоторый COM-объект может передать вам вариант (например, тип VARIANT или _variant_t), который может содержать double, float, int или любой другой .

Если вам приходится иметь дело с COM-объектами в коде Windows C ++, вы увидите повсюду типы вариантов.

2 голосов
/ 29 января 2010

SDL использует объединение для представления событий: http://www.libsdl.org/cgi/docwiki.cgi/SDL_Event.

2 голосов
/ 23 декабря 2009
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 голосов
/ 23 декабря 2009

Объединения полезны, если у вас есть различные виды сообщений, и в этом случае вам не нужно знать точный тип на каких-либо промежуточных уровнях. Только отправитель и получатель должны проанализировать фактическое сообщение сообщения. Любые другие уровни действительно должны знать размер и, возможно, информацию об отправителе и / или получателе.

1 голос
/ 25 ноября 2010

Я знаю, что немного опоздал на вечеринку, но в качестве практического примера, тип данных Variant в VBScript, как мне кажется, реализован как Union. Следующий код является упрощенным примером, взятым из статьи, найденной иначе здесь

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

Фактическая реализация (как говорится в статье) находится в заголовочном файле oaidl.h C.

1 голос
/ 23 декабря 2009

ты имеешь в виду что-то подобное?

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

ДОБАВЛЕНО

Недавно я использовал это на нашей машине AIX для преобразования 64-битного машинного идентификатора в байтовый массив.

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 голос
/ 24 декабря 2009
  • При чтении сериализованных данных, которые необходимо преобразовать в определенные типы.
  • При возврате семантических значений от lex до yacc. (yylval)
  • При реализации полиморфного типа, особенно такого, который читает DSL или общий язык
  • При реализации диспетчера, который специально вызывает функции, предназначенные для разных типов.
...