Подтвердить что ты не робот

C: Где профсоюз практически используется?

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

    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

Я обычно использовал союзы, в которых вы хотите иметь разные представления данных например 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 Вы также можете добиться того же, что и при маскировке и смещении бит i.e

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

но я считаю, что союзный подход более изящный

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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

Ответ 8

Вы имеете в виду что-то вроде этого?

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

ADDED

Недавно я использовал это на нашей машине 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

Ответ 9

Я использовал иногда союзы таким образом

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

Затем вы можете объявлять массивы разных значений, хранить более или менее эффективно данные и выполнять некоторые "полиморфные" операции, такие как:

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

Ответ 10

Вот еще один пример, когда объединение может быть полезным.

(не моя собственная идея, я нашел это на документе, обсуждающем оптимизация С++)

начать кавычка

.... Союзы также могут использоваться для экономии места, например.

сначала неединичный подход:

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

Здесь можно использовать одну и ту же область памяти для a и b, потому что их диапазоны в реальном времени делают не перекрываются. Вы можете сэкономить много пространства cpu-cache, объединив a и b в объединении:

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

Использование союза - это не безопасная практика программирования, конечно, потому что вы не получите предупреждение от компилятора, если использование a и b перекрывается. Вы должны использовать этот метод только для больших объектов, которые занимают много места в кеше....

конец qoute

Ответ 11

  • При чтении сериализованных данных, которые необходимо принуждать к определенным типам.
  • При возврате семантических значений от lex до yacc. (yylval)
  • При реализации полиморфного типа, особенно тех, которые читают DSL или общий язык
  • При внедрении диспетчера, который специально вызывает функции, предназначенные для разных типов.

Ответ 12

Недавно я думаю, что я видел некоторый союз, используемый в векторном программировании. векторное программирование используется в технология Intel MMX, аппаратное обеспечение GPU, IBM Cell Broadband Engine и т.д.

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

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

если вы пройдете путь в многоядерном программировании PlayStation 3 или графическом программировании, вы сможете столкнуться с большим количеством этих материалов.

Ответ 13

Я знаю, что немного опаздываю на вечеринку, но, как представляется, в качестве практического примера тип данных 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.

Ответ 14

Пример:

При использовании разных типов сокетов, но вам нужен тип comon.

Ответ 15

Еще один пример: сохранить выполнение отливок.

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

вместо:

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

Ответ 16

Для удобства я использую объединения, чтобы позволить мне использовать один и тот же класс для хранения значений xyzw и 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

Ответ 17

Многие примеры объединений можно найти в <X11/Xlib.h>. Немногие другие находятся в некоторых стеках IP (например, в BSD <netinet/ip.h>).

Как правило, реализации протокола используют конструкцию union.