联合体:
联合体也是一种自定义类型, 特点是成员变量公用一块空间。所以也叫共用体。
联合体的性质
先定义一个联合体:
然后我创建一个联合体变量:
现在探究当修改一个成员变量的值时, 其他成员变量的值能否被修改(既然共用内存, 那么其他成员的值应该是能被修改的)。
现在观察的是该结构体变量的内存空间, 图中画红线的就是结构体变量的内存空间。
此时程序运行刚刚将un.a赋值。
通过观察我们可以发现, un.c的赋值改变了un.a的值。
现在我们再来探究令一条性质:联合体的成员变量的存储位置是从哪里开始。
由图中我们可以发现, 联合体的成员都是在联合体变量的首地址开始存储。
联合体的初始化
联合体的初始化方式有两种, 一种是通过另一个联合体直接进行赋值。
union Un
{
char a;
int b;
};
int main()
{
union Un k;
k.a = 10;
union Un l = k;
printf("d", k.a);
return 0;
}
另一种是通过括号,但是只能赋值联合体的第一个元素:
union Un
{
char a;
int b;
};
int main()
{
Un k = { 0x11223344 };
printf("%x", k.b);
return 0;
}
这种情况下只能在括号中写一个值, 并且这个值是赋值给联合体的第一个元素的。 也就是说,虽然图中我写了0x11223344这个整形数字, 但是赋值给k.a后发生截断。 只赋给了k.a0x44, 那么k.b也就是0x00000044了。
注意:括号里只能写一个值, 如果写两个以及以上, 那么就会报错。
联合体内存的大小
那么,联合体的内存大小怎么计算呢?
联合体的内存大小至少要比最大的成员变量的大小要大, 因为只有这样才能保证该成员变量的数据被存储下来。
其次联合体的内存大小也会用到对齐数。 当成员变量的最大值不是对齐数的整数倍时, 那么联合体的大小就是那个比成员变量最大值大的那个对齐数的整数倍。
如:
利用联合体求取大小端
我们都知道数据在内存中的储存是有大小端问题的(如果忘记了,请前往我的c语言专栏——c语言各个数据类型在内存中的存储方式),那么如何利用c语言来求取编译器是大端存储还是小端存储呢?
现在来实现一下:
首先, 我们通过上面的分析,已经知道了联合体的成员变量都是在联合体变量的首地址开始存储, 也就是低地址处开始存储。 所以对于un.a来说, 访问的话那么访问的就是联合体的第一个偏移量内的空间。
既然访问的是第一个偏移量内的空间也就是低地址处的空间, 并且这个空间存储的是0x44。那么我们就可以断定, un.c是将高位字节序的数据存储到了高地址处, 低位字节序的数据存储到了低地址处。