结构体和联合体的区别

466
有没有一个好的例子可以说明structunion之间的区别? 基本上我知道struct使用其成员的所有内存,而union使用最大成员的内存空间。在操作系统层面上还有其它的区别吗?
17个回答

4

结构体和联合体的区别在于内存分配。

简单来说,结构体会为其内部所有成员创建内存空间,而联合体只会为需要最大内存空间的成员创建内存空间。

考虑以下代码:

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

Ref:http://www.codingpractise.com/home/c-programming/structure-and-union/


3

联合的用途 当需要进行专门类型转换时,经常使用联合。 为了了解联合的有用性。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()。但我想展示一个例子来说明如何使用联合体。


3

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

当我们确定只有一个变量会被使用并且希望充分利用当前内存时,通常会使用联合体,因为它只占用一个大小等于最大类型的内存块。

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

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

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

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


2

在编写下面的字节顺序函数时,联合结构非常有用。使用结构体是不可能的。

int main(int argc, char **argv) {
    union {
        short   s;
        char    c[sizeof(short)];
    } un;

    un.s = 0x0102;

    if (sizeof(short) == 2) {
        if (un.c[0] == 1 && un.c[1] == 2)
            printf("big-endian\n");
        else if (un.c[0] == 2 && un.c[1] == 1)
            printf("little-endian\n");
        else
            printf("unknown\n");
    } else
        printf("sizeof(short) = %d\n", sizeof(short));

    exit(0);
}
// Program from Unix Network Programming Vol. 1 by Stevens.

1
我建议在需要对具有一组独立属性的事物进行建模时使用结构,而在实体有多种形式且一次只能存在一种形式时使用联合。

让我们看看它们可以应用的两个地方

您需要存储和更新汽车的值。为此,我们需要记录汽车的所有属性,如型号、里程、价格和燃油类型。这些值始终存在于汽车中,它们不依赖于其他值。 因此,我们需要一种数据类型,不仅可以存储所有的属性,还可以确保它们的正确更新。这类任务可以使用结构来完成。

struct car{
    char model[];
    int mileage;
    int price;
    char fuel_type[];
};

一个组织需要从大量客户那里收集数据以进行付款验证。为了确保数据完整性和客户安全,该组织被要求从个人那里获取最少的详细信息。这些详细信息可以是您的 PAN 号码、账号或选民身份证。现在,由于我们需要收集其中任何一项详细信息,并同时具有内存效率,因此我们可以在此处使用联合。它只会保存提供给它的单个值。

union verification_details{
    char account_number[10];
    char PAN[10];
    char voter_id[10];
};

我找到了一篇很好地解释了这个问题的文章:结构体和联合体的区别

1
一个联合(Union)与一个结构体(Struct)不同,联合会重复覆盖其他内容:它重新定义相同的内存,而结构体则是一个接着一个地定义,没有重叠或重新定义。

0
有没有好的例子可以说明结构体和联合体之间的区别?
嵌入式系统应用中的实际例子如下。它只使用了联合体,但清楚地展示了联合体的功能。
编写I2C通信协议的函数使用联合类型,该类型用于数据存储,当从传递给它的数组中检索数据时使用。
union data
{
    uint32_t packet;
    uint8_t  packetbyte[4];
} txdata;

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

循环结束后,txdata.packet 包含 4 个字节的数据,这些数据被连续地存储到 txdata 联合体中。作为在通信总线上传输数据的最后一步,将 txdata.packet 写入 32 位缓冲区,写入后启动写入序列。然后在下一次执行 for 循环之前通过 txdata.packet = 0 重置内容。

这样,I2C 主机可以重新传输 32 位数据包,直到传递的输入数据被发送并写入函数被终止。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接