有什么好的例子可以说明结构体和联合体的区别吗? 基本上我知道struct使用了它成员的所有内存,而union使用了最大的成员内存空间。还有其他操作系统级别的差异吗?


当前回答

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

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

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

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

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

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

其他回答

你拥有它,仅此而已。 那么,工会的意义是什么呢?

您可以在相同的位置中放入不同类型的内容。你必须知道你在联合中存储的东西的类型(所以你经常把它放在一个带有type标签的结构体中…)

为什么这很重要?并不是为了获得空间。是的,你可以获得一些位或做一些填充,但这已经不是重点了。

这是为了类型安全,它允许你做某种“动态类型”:编译器知道你的内容可能有不同的含义,你如何解释它的确切含义取决于你在运行时。如果你有一个指针可以指向不同的类型,你必须使用联合,否则你的代码可能会因为别名问题而不正确(编译器会对自己说“哦,只有这个指针可以指向这种类型,所以我可以优化这些访问……”,糟糕的事情可能会发生)。

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

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

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

我发现下面的文章解释得很好:结构和联合的区别

As you already state in your question, the main difference between union and struct is that union members overlay the memory of each other so that the sizeof of a union is the one , while struct members are laid out one after each other (with optional padding in between). Also an union is large enough to contain all its members, and have an alignment that fits all its members. So let's say int can only be stored at 2 byte addresses and is 2 bytes wide, and long can only be stored at 4 byte addresses and is 4 bytes long. The following union

union test {
    int a;
    long b;
}; 

could have a sizeof of 4, and an alignment requirement of 4. Both an union and a struct can have padding at the end, but not at their beginning. Writing to a struct changes only the value of the member written to. Writing to a member of an union will render the value of all other members invalid. You cannot access them if you haven't written to them before, otherwise the behavior is undefined. GCC provides as an extension that you can actually read from members of an union, even though you haven't written to them most recently. For an Operation System, it doesn't have to matter whether a user program writes to an union or to a structure. This actually is only an issue of the compiler.

union和struct的另一个重要属性是,它们允许指向它们的指针可以指向其任何成员的类型。因此,以下是有效的:

struct test {
    int a;
    double b;
} * some_test_pointer;

Some_test_pointer可以指向int*或double*。如果将一个test类型的地址转换为int*,它将指向它的第一个成员,实际上是a。工会也是如此。因此,因为联合将始终具有正确的对齐方式,您可以使用联合来使指向某些类型的指针有效:

union a {
    int a;
    double b;
};

这个联合实际上可以指向int型和double型:

union a * v = (union a*)some_int_pointer;
*some_int_pointer = 5;
v->a = 10;
return *some_int_pointer;    

实际上是有效的,正如C99标准所述:

对象的存储值只能由具有以下类型之一的左值表达式访问: 与对象的有效类型兼容的类型 ... 在其成员中包含上述类型之一的聚合或联合类型

编译器不会优化出v->a = 10;因为它可能会影响*some_int_pointer的值(该函数将返回10而不是5)。

“union”和“struct”是C语言的构造。谈论它们之间的“操作系统级别”差异是不合适的,因为如果您使用一个或另一个关键字,则是编译器产生不同的代码。