您现在的位置是:首页 >技术杂谈 >C——Union是什么?Union和Struct这么像,区别在哪?为什么还要创造出union呢?需要在哪里使用呢?网站首页技术杂谈
C——Union是什么?Union和Struct这么像,区别在哪?为什么还要创造出union呢?需要在哪里使用呢?
在 C 语言中,有一种叫做union
的变量,是用来在不同的情况下,存放不同类型和大小的对象的变量。这与结构体struct
很相似:结构体是一个或多个变量的集合。
union 的声明方式非常简单,也与struct
一模一样,如下:
union u_tag {
int ival;
char *sval;
} u;
可以看到,唯一的不同就是结构体中的struct
变成了union
。
使用方法也一模一样:
//一般变量
union_name.val
//指针
union_pointer->val
二者这么像,那么二者的区别在哪里呢?或者说,为什么要弄两个这么像的东西呢?C 又不是 C++,一些功能是由不同的小组开发的,一些功能上会重叠。
首先是表面的不同,struct
和union
在使用目的上完全不一样,union
并不像struct
会同时存放大括号中列出的每个变量,如果你尝试下面的代码
union u_tag {
int a;
int b;
} u;
int main()
{
u.a=1;
u.b=2;
printf("u_tag: %d
", u.ival);
return 0;
}
那么输出的结果为:
u_tag: 2
这里的结果不是出错了,是因为union
并不会像结构体一样,去根据前面的u.a=1
输出1
,由于只能存放一种数据,所以后面的u.b=2
覆盖了原本u
存放的值。
所以说,union
内部声明的变量可以理解成是一种可能,而不是实际的对象或成员变量。
并且由于union
内部只有一个值,所以一般不会使用相同的数据类型。至于目前包含什么数据类型,这是编程的时候需要程序员注意的。一般是用一个变量u_type
,然后再用判断语句来判断当前包含的类型。
但是struct
和union
最核心的不同,也是union
诞生的理由是:分配空间的机制。
如果你用sizeof()
测量下面两个数据的尺寸
union u_tag {
int ival;
float fval;
char *sval;
} u;
struct s_tag {
int ival;
float fval;
char *sval;
} s;
会发现,u_tag
的尺寸是 8 个字节,但是s_tag
的尺寸是 16 个字节 。这是因为union
相当于给内部声明的数据类型留了一个最大空间,而struct
是给每个数据类型都留了各自的空间。
在现在的绝大部分机器上,int
类型为 4 字节,float
类型为 4 字节,cahr *
类型为 8 个字节。所以u
就占据了最大空间,也就是 8 个字节,而s
则每个都留了各自的空间,也就是 4+4+8=16 字节。
那么需要在什么时候使用union
呢?
首先根据其存放一种数据的特点,可以用来做一些通用计算,比如说浮点数和整数的切换等。
其次上面的使用目的下,节省空间了。虽然这种情况下也可以使用结构体,但是上面三种数据类型就差一倍大小的情况算好的。因为内存地址分配机制,一些类型的数据的地址是由特殊要求的,比如说在一些机器上,int
需要在偶数位的地址。
下面就是一个例子,但是整数的地址限制并不是在偶数,而是 4 的倍数。
struct s_tag {
int ival;
char a;
} s;
这个结构体的大小为 8 个字节,你可以自己试试看是不是这个大小。
并且由于编译器是顺序读取的,所以如果你写成下面这样
struct s_tag {
int a;
char b;
int c;
char d;
} s;
那么这个结构体的大小为 16 字节。这种情况下可以将同一类的数据写在一起,可以节约一些空间,如下:
struct s_tag {
int a;
int c;
char b;
char d;
} s;
这样这个结构体所占用的空间大小就为 12 字节了。而如果使用union
,那么无论什么顺序,大小一直为 4 字节。随着数据类型的可能性越来越多,节约空间的必要性就凸显出来了。
希望能帮到有需要的人~