有什么好的例子可以说明结构体和联合体的区别吗? 基本上我知道struct使用了它成员的所有内存,而union使用了最大的成员内存空间。还有其他操作系统级别的差异吗?
当前回答
联合在一些场景中很有用。 Union可以是非常低级的操作工具,比如为内核编写设备驱动程序。
其中一个例子是通过使用具有位域和浮点数的结构并集来解剖浮点数。我在浮点数中保存了一个数字,之后我可以通过该结构体访问浮点数的特定部分。该示例展示了如何使用联合来从不同角度查看数据。
#include <stdio.h>
union foo {
struct float_guts {
unsigned int fraction : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} fg;
float f;
};
void print_float(float f) {
union foo ff;
ff.f = f;
printf("%f: %d 0x%X 0x%X\n", f, ff.fg.sign, ff.fg.exponent, ff.fg.fraction);
}
int main(){
print_float(0.15625);
return 0;
}
看看维基百科上的单精度描述。我使用了这个例子和其中的神奇数字0.15625。
联合还可用于实现具有多个备选项的代数数据类型。我在O'Sullivan, Stewart和Goerzen的《Real World Haskell》一书中找到了一个例子。 请查看受歧视的工会部分。
干杯!
其他回答
结构分配其中所有元素的总大小。
一个联合只分配它最大的成员所需要的内存。
从技术上讲,非指:
假设:椅子=记忆块,人=变量
结构:如果有3个人,他们可以坐在相应大小的椅子上。
工会:如果有3个人,只有一张椅子可以坐,所有人都需要在他们想坐的时候使用同一把椅子。
技术上讲是指:
下面提到的程序对结构和联合进行了深入研究。
struct MAIN_STRUCT
{
UINT64 bufferaddr;
union {
UINT32 data;
struct INNER_STRUCT{
UINT16 length;
UINT8 cso;
UINT8 cmd;
} flags;
} data1;
};
MAIN_STRUCT size =sizeof(UINT64) for bufferaddr + sizeof(UNIT32) for union + 32 bit for padding(取决于处理器架构)= 128 bits。 对于结构,所有成员连续获取内存块。
Union获得一个最大大小成员的内存块(这里是32位)。 在联合内部还有一个结构体(INNER_STRUCT),它的成员获得一个总大小为32位(16+8+8)的内存块。在联合中,可以访问INNER_STRUCT(32位)成员或data(32位)。
结构和联合的区别是什么?
简单的回答是:区别在于内存分配。 解释: 在结构中,将为结构内部的所有成员创建内存空间。 在联合内存空间将只为需要最大内存空间的成员创建。 考虑下面的代码:
struct s_tag
{
int a;
long int b;
} x;
union u_tag
{
int a;
long int b;
} y;
这里在struct和union内部有两个成员:int和long int。在32位操作系统中,int的内存空间为:4字节,long int的内存空间为:8。
因此,对于struct, 4+8=12个字节将被创建,而对于union,将创建8个字节
代码示例:
#include<stdio.h>
struct s_tag
{
int a;
long int b;
} x;
union u_tag
{
int a;
long int b;
} y;
int main()
{
printf("Memory allocation for structure = %d", sizeof(x));
printf("\nMemory allocation for union = %d", sizeof(y));
return 0;
}
裁判:http://www.codingpractise.com/home/c-programming/structure-and-union/
对于联合,您只应该使用其中一个元素,因为它们都存储在同一个位置。这在您想要存储可能是几种类型之一的内容时非常有用。另一方面,结构体的每个元素都有单独的内存位置,并且它们都可以一次使用。
为了给出它们使用的一个具体例子,我不久前正在研究一个Scheme解释器,我实际上是将Scheme数据类型覆盖到C数据类型上。这涉及到在一个结构体中存储一个指明值类型的枚举和一个用于存储该值的联合。
union foo {
int a; // can't use both a and b at once
char b;
} foo;
struct bar {
int a; // can use both a and b simultaneously
char b;
} bar;
union foo x;
x.a = 3; // OK
x.b = 'c'; // NO! this affects the value of x.a!
struct bar y;
y.a = 3; // OK
y.b = 'c'; // OK
编辑:如果你想知道将x.b设置为“c”会改变x.a的值,从技术上讲,这是未定义的。在大多数现代机器上,char是1字节,int是4字节,所以给x.b的值'c'也给x.a的第一个字节相同的值:
union foo x;
x.a = 3;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
打印
99, 99
为什么这两个值是一样的?因为int 3的最后3个字节都是0,所以它也被读为99。如果我们为x.a输入一个更大的数字,你会发现情况并非总是如此:
union foo x;
x.a = 387439;
x.b = 'c';
printf("%i, %i\n", x.a, x.b);
打印
387427, 99
为了更仔细地查看实际的内存值,让我们设置并打印十六进制的值:
union foo x;
x.a = 0xDEADBEEF;
x.b = 0x22;
printf("%x, %x\n", x.a, x.b);
打印
deadbe22, 22
您可以清楚地看到0x22覆盖了0xEF的位置。
BUT
在C语言中,int类型的字节顺序没有定义。这个程序在我的Mac上用0x22覆盖了0xEF,但是在其他平台上它会覆盖0xDE,因为组成int的字节的顺序颠倒了。因此,在编写程序时,永远不要依赖于覆盖联合中特定数据的行为,因为它是不可移植的。
有关字节排序的更多信息,请参阅endianness。
有什么好的例子可以说明“结构体”和“联合体”之间的区别吗?
一种假想的通信协议
struct packetheader {
int sourceaddress;
int destaddress;
int messagetype;
union request {
char fourcc[4];
int requestnumber;
};
};
在这个假想的协议中,已经指定了基于“消息类型”的消息头中的下面位置要么是请求号,要么是四个字符的代码,但不是两者都是。简而言之,联合允许相同的存储位置表示多个数据类型,可以保证您在任何时候只希望存储其中一种类型的数据。
联合在很大程度上是基于C作为系统编程语言的传统的低级细节,其中“重叠”存储位置有时以这种方式使用。如果数据结构一次只保存几种类型中的一种,则有时可以使用联合来节省内存。
一般来说,操作系统不关心或不知道结构体和并体——它们都只是内存块。struct是存储多个数据对象的内存块,这些对象不重叠。联合是存储多个数据对象的内存块,但只能存储其中最大的一个,因此在任何时候只能存储其中一个数据对象。