У меня есть пример со мной, где гарантируется выравнивание типа, union max_align. Я ищу еще более простой пример, в котором профсоюз используется практически, чтобы объяснить моего друга.
C: Где профсоюз практически используется?
Ответ 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
Союзы полезны, если у вас есть разные типы сообщений, и в этом случае вам не нужно знать на каких-либо промежуточных уровнях точный тип. Только отправителю и получателю необходимо разобрать фактическое сообщение сообщения. Любые другие уровни действительно должны знать размер и, возможно, информацию отправителя и/или получателя.
Ответ 7
SDL использует объединение для представления событий: http://www.libsdl.org/cgi/docwiki.cgi/SDL_Event.
Ответ 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.
Ответ 18
Союзы также могут быть полезны, если type punning, что желательно в нескольких местах (например, некоторые методы для алгоритмы сравнения с плавающей запятой).