有什么好的例子可以说明结构体和联合体的区别吗? 基本上我知道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》一书中找到了一个例子。 请查看受歧视的工会部分。

干杯!

其他回答

有什么好的例子可以说明“结构体”和“联合体”之间的区别吗?

一种假想的通信协议

struct packetheader {
   int sourceaddress;
   int destaddress;
   int messagetype;
   union request {
       char fourcc[4];
       int requestnumber;
   };
};

在这个假想的协议中,已经指定了基于“消息类型”的消息头中的下面位置要么是请求号,要么是四个字符的代码,但不是两者都是。简而言之,联合允许相同的存储位置表示多个数据类型,可以保证您在任何时候只希望存储其中一种类型的数据。

联合在很大程度上是基于C作为系统编程语言的传统的低级细节,其中“重叠”存储位置有时以这种方式使用。如果数据结构一次只保存几种类型中的一种,则有时可以使用联合来节省内存。

一般来说,操作系统不关心或不知道结构体和并体——它们都只是内存块。struct是存储多个数据对象的内存块,这些对象不重叠。联合是存储多个数据对象的内存块,但只能存储其中最大的一个,因此在任何时候只能存储其中一个数据对象。

联合的用法 当需要特殊类型的对话时,联合经常被使用。 来了解联合的用处。c/c标准库没有定义专门为将短整数写入文件而设计的函数。使用fwrite()会导致简单操作的开销过大。然而,使用联合可以很容易地创建一个函数,该函数将一个短整数的二进制每次一个字节写入文件。我假设短整数是2字节长

示例:

#include<stdio.h>
union pw {
short int i;
char ch[2];
};
int putw(short int num, FILE *fp);
int main (void)
{
FILE *fp;
fp fopen("test.tmp", "wb ");
putw(1000, fp); /* write the value 1000 as an integer*/
fclose(fp);
return 0;
}
int putw(short int num, FILE *fp)
{
pw word;
word.i = num;
putc(word.c[0] , fp);
return putc(word.c[1] , fp);
}    

虽然我用短整数调用putw(),但可以使用putc()和fwrite()。但是我想展示一个例子来说明如何使用联合

有什么好的例子可以说明结构体和联合体的区别吗?

下面是来自嵌入式系统应用的真实例子。它只使用联合,但它清楚地显示了联合的功能。

I2C通信协议的写函数在从传递给它的数组中检索数据时使用联合类型,用于数据存储。

union data
{
    uint32_t packet;
    uint8_t  packetbyte[4];
} txdata;

通过指针传递给write函数的数组包含一个字节大小的元素。在for循环中,这些字节分四个步骤逐一提取,并存储到txdata的各个元素中。packetbyte成员。

循环结束后,txdata。数据包包含4个字节的数据,这些数据被连续存储到txdata联合中。作为通过通信总线发送数据的最后一步,txdata。数据包被写入32位缓冲区,在被写入后,32位缓冲区启动写序列。然后通过txdata重置内容。在next for循环开始执行之前,Packet = 0。

通过这种方式,I2C主机可以重新传输32位数据包,直到发送通过的输入数据并终止写入功能。

简单的回答是:结构体是一个记录结构体:结构体中的每个元素分配新的空间。一个结构体

struct foobarbazquux_t {
    int foo;
    long bar;
    double baz; 
    long double quux;
}

为每个实例在内存中分配至少(sizeof(int)+sizeof(long)+sizeof(double)+sizeof(long double))字节。(“至少”是因为架构对齐约束可能迫使编译器填充结构。)

另一方面,

union foobarbazquux_u {
    int foo;
    long bar;
    double baz; 
    long double quux;
}

分配一个内存块并给它四个别名。因此sizeof(union foobarbazquux_u)≥max((sizeof(int),sizeof(long),sizeof(double),sizeof(long double)),同样有可能添加一些对齐。

结构是不同数据类型的集合,其中可以驻留不同类型的数据 每一个都有自己的内存块。

当我们确定一次只使用其中一个变量,并且希望充分利用当前内存时,我们通常使用联合,因为它只获得一个等于最大类型的内存块。

struct emp
{
    char x; //1 byte
    float y; //4 byte
} e;

它获得的总内存:=>5字节。

union emp
{
    char x; //1 byte
    float y; //4 byte
} e;

它获得的总内存:4字节。