我有一个例子,我保证了类型的对齐,union max_align。我正在寻找一个更简单的例子,其中实际上使用了union来解释我的朋友。
答案 0 :(得分:33)
我通常在解析文本时使用联合。我使用这样的东西:
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 of union。
答案 1 :(得分:6)
我通常使用你想拥有不同数据视图的工会 例如一个32位颜色值,您需要32位val和红色,绿色,蓝色和alpha分量
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)
但我觉得工会方法更优雅
答案 2 :(得分:5)
通过将特定端口映射到内存,以字节方式和按位方式访问寄存器或I / O端口,请参见下面的示例:
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 :(得分:3)
在Windows世界中,unions
通常用于实现tagged variants,它们是(或者在.NET之前?)在COM objects之间传递数据的一种标准方式。
这个想法是union
类型可以提供一个自然界面,用于在两个对象之间传递任意数据。某些COM对象可以传递一个变体(例如,类型VARIANT
或_variant_t
),其中可能包含double
,float
,int
或其他任何内容。< / p>
如果必须在Windows C ++代码中处理COM对象,则会在整个地方看到变体类型。
答案 4 :(得分:2)
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;
};
答案 5 :(得分:2)
SDL使用联合来表示事件:http://www.libsdl.org/cgi/docwiki.cgi/SDL_Event。
答案 6 :(得分:2)
如果您有不同类型的消息,联合会很有用,在这种情况下,您不必知道任何中间级别的确切类型。只有发送方和接收方需要解析消息实际消息。任何其他级别只需要知道大小以及可能的发送者和/或接收者信息。
答案 7 :(得分:1)
我知道我有点迟到了,但作为一个实际例子,我相信VBScript中的Variant
数据类型是以Union
实现的。以下代码是一个简单的示例,取自另外找到的文章here
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头文件中找到。
答案 8 :(得分:1)
最近我想我在vector programming看到了一些联盟。矢量编程用于intel MMX technology,GPU硬件,IBM's Cell Broadband Engine等。
向量可以对应于128位寄存器。它非常常用于SIMD架构。由于硬件具有128位寄存器,因此可以在寄存器/变量中存储4个单精度浮点。构造,转换,提取向量的单个元素的简单方法是使用union。
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多核编程或图形编程中走一条路,你很有可能会面对更多这些东西。
答案 9 :(得分:1)
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
答案 10 :(得分:1)
我以某种方式使用了工会
//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;
然后你可以声明不同类型值的数组,存储更多或更低效的数据,并进行一些“polimorph”操作,如:
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;
}
}
答案 11 :(得分:1)
这是联盟可能有用的另一个例子。
(不是我自己的想法,我在讨论的文件中找到了这个 c++ optimizations)
<强>开始引号强>
....工会也可用于节省空间,例如
首先是非工会方法:
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使用相同的存储区域,因为它们的有效范围可以 不重叠。您可以通过在联合中加入a和b来节省大量 cpu-cache space :
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 强>
答案 12 :(得分:1)
lex
返回到yacc
时。 (yylval
)答案 13 :(得分:0)
许多工会的例子都可以在<X11/Xlib.h>
中找到。很少有人在某些IP堆栈中(例如在BSD <netinet/ip.h>
中)。
作为一般规则,协议实现使用union构造。
答案 14 :(得分:0)
联盟在type punning时也很有用,这在少数几个地方是可取的(例如某些floating-point comparison算法技术)。
答案 15 :(得分:0)
为方便起见,我使用工会让我使用同一个类来存储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
答案 16 :(得分:0)
另一个例子:保存铸件。
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));
}
答案 17 :(得分:0)
示例:
使用不同的套接字类型时,您需要引用通用类型。