struct
和union
之间的区别?
基本上我知道struct
使用其成员的所有内存,而union
使用最大成员的内存空间。在操作系统层面上还有其它的区别吗?结构体和联合体的区别在于内存分配。
简单来说,结构体会为其内部所有成员创建内存空间,而联合体只会为需要最大内存空间的成员创建内存空间。
考虑以下代码:
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/
联合的用途 当需要进行专门类型转换时,经常使用联合。 为了了解联合的有用性。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()。但我想展示一个例子来说明如何使用联合体。
结构体是一种包含不同数据类型的集合,其中不同类型的数据可以驻留在其中,并且每个数据类型都有自己的内存块。
当我们确定只有一个变量会被使用并且希望充分利用当前内存时,通常会使用联合体,因为它只占用一个大小等于最大类型的内存块。
struct emp
{
char x; //1 byte
float y; //4 byte
} e;
它获得的总内存为:=>5字节。
union emp
{
char x; //1 byte
float y; //4 byte
} e;
它获得的总内存:4字节。
在编写下面的字节顺序函数时,联合结构非常有用。使用结构体是不可能的。
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.
让我们看看它们可以应用的两个地方
您需要存储和更新汽车的值。为此,我们需要记录汽车的所有属性,如型号、里程、价格和燃油类型。这些值始终存在于汽车中,它们不依赖于其他值。 因此,我们需要一种数据类型,不仅可以存储所有的属性,还可以确保它们的正确更新。这类任务可以使用结构来完成。
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];
};
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 位数据包,直到传递的输入数据被发送并写入函数被终止。