C语言自定义数据类型详解(四)——联合体
好的,接下来我们来学习最后一个自定义数据类型——联合体。
一、什么是联合体:
联合体又叫共用体,用关键字union来进行定义。又因为所有的成员变量共用同一段内存空间(关于这一点,我们不久就会加以验证),所以它是一种比较特殊的自定义类型。
二、联合体的内存布局:
(1)验证联合体成员共用同一块空间:
我们前面已经提到了说联合体它的成员变量都是共用同一段内存空间的,我们可以通过下面这个代码对这一结论加以验证:
#include<stdio.h>
union Uo
{int a;char i;
};
int main()
{union Uo u;printf("sizeof(u) == %zd\n", sizeof(u));printf("%p\n", &(u.a));printf("%p\n", &(u.i));return 0;
}
运行效果:
我们发现对于联合体u,它的大小是4Byte,且无论是针对它的成员变量a取地址,还是针对它的成员变量i取地址,它的结果都是一样的。
我们可以进一步做一些事情,我们修改变量a的值,然后来观察成员变量i是否会受影响。因此我们写出下面这个代码:
#include<stdio.h>
union Uo
{int a;char i;
};
int main()
{union Uo u;u.a = 0x44332211;//%x是以十六进制打印整数:printf("0x%x\n", u.a);printf("0x%x\n", u.i);return 0;
}
运行结果(注意这里的结果你可能和我不一样,因为这和机器是小端字节序,还是大端字节序有关系。而博主现在是小端字节序的机器):
我们发现对联合体中某一个成员变量的值进行修改,也会影响到其他的成员变量。这里又进一步佐证了联合体的成员变量共用同一段内存空间这一事实。
综上,对于联合体变量union Uo u来说,它的内存布局是:
(2)联合体内存大小的计算:
有很多小伙伴在联合体这里会犯一个错误,认为联合体的大小就是最大成员变量的大小。但是其实不然,就比如说下面这个代码场景:
#include<stdio.h>
union Uo
{int a;char i[5];
};
int main()
{union Uo u;printf("%zd\n", sizeof(u));return 0;
}
运行结果:
所以关于联合体的大小:我们认为联合体的大小至少是最大成员变量的大小。当最大成员变量的大小不是最大对齐数的整数倍时(关于对齐数可以看博主的前面的博客C语言自定义数据类型详解(二)——结构体类型(下)-CSDN博客)需要进行内存对齐。
三、联合体的应用场景:
我们试想这么一个场景:我们要求设计一些数据类型来存储图书,布袋,衬衫这三个商品的一些属性。那首先分析这三个商品,它们都有各自以下这些属性:
图书:库存量,价格,书名,作者;
布袋:库存量,价格,样式;
衬衫:库存量,价格,颜色,尺寸;
那据此,你可不可以设计下面这样的:
struct book
{int _stock; //库存float _price;//价格char _bookName[30];//书名char _writer[30]; //作者
};
struct bag
{int _stock; //库存float _price;//价格char _style[30];//样式
};
struct shirt
{int _stock; //库存float _price;//价格char color[15];//颜色size_t _size; //尺寸
};
但是你有没有觉得这个设计比较冗余,因为库存量和价格都是这些商品共有的属性。这在C++,Java里面可以通过继承的方式来消除这种设计上的冗余,那C语言呢?OK,C语言可以借助联合体设计出下面这个结构体:
#include<stdio.h>
#include<string.h>
struct commodity
{int _stock; //库存float _price;//价格//这里面都是匿名结构体和匿名联合体哦!union{struct{char _bookName[30];//书名char _writer[30]; //作者} _book;struct{char _style[30];//样式} _bag;struct{char color[15];//颜色size_t _size; //尺寸} _shirt;}_item;
};
int main()
{struct commodity com;//注意这里的_writer是char* const的指针(常量指针),所以不能写作com._item._book._writer = "MoYan";strcpy(com._item._book._writer, "MoYan");printf("The writer of the book is %s\n", com._item._book._writer);return 0;
}
OK,这次的知识分享就到这里了,我们下次再见!