前言:
此时兄弟们对“c语言共用体结构体”大概比较注意,你们都想要学习一些“c语言共用体结构体”的相关知识。那么小编也在网络上搜集了一些对于“c语言共用体结构体””的相关知识,希望我们能喜欢,小伙伴们快快来了解一下吧!引言
在C语言中,每个数据类型都有其特定的作用或使用场景。 前面我们详细的分析了数组,结构体,今天我们来讲讲共用体(union),所谓的共用体就是使用覆盖技术让数据成员之间相互覆盖,以实现不同数据成员共用同一段内存。先引出概念,接下来我们从共用体与其他的数据类型区别,到共用体类型如何定义,哪些场景会使用共用体等等,逐步分析。
共用体和结构体区别
共用体(union)和结构体(struct)在类型定义, 变量定义,使用方法上都非常相似:
//共用体类型定义union test{ int a char b;};
变量的定义和使用:
//定义共用体变量t1 union test t1; //使用共同体t1成员 t1.a = 23;
那两者有什么区别呢?结构体好比是一个袋子,袋子里面装了各种各样的东西,每个东西都是独立存在的,占据了袋子体积; 而共用体的各个成员是一体的,彼此不独立,它们使用同一块内存空间,可以理解为:有时候是这个元素,有时候是另外一个元素(就像是一个多面人),有不同的形态,更准确的说是同一块内存空间有多种解释方式!通过以下示意图感受下:
接下来我们通过实例代码,来理解其本质区别:
#include <stdio.h>//定义结构体类型struct test1{ int a; char b;};//定义共用体类型union test2{ int a; char b;};int main(void){ //定义结构体变量t1 struct test1 t1; //定义共用体变量2 union test2 t2; t1.a = 23; t2.a = 24; //打印变量元素 printf("t1.b = %d.\n", t1.b); printf("t2.b = %d.\n", t2.b);//打印结构体t1元素的地址 printf("&t1.a = %p.\n", &t1.a); printf("&t1.b = %p.\n", &t1.b); //打印共用体t2元素地址 printf("&t2.a = %p.\n", &t2.a); printf("&t2.b = %p.\n", &t2.b); return 0;}
说明:
1.我们分别定义了结构体变量t1, 和共用体变量t2
2. 初始化了结构体t1中的元素a, 赋值为23,但是元素b未初始化
3. 初始化了共用体t2中的元素a, 赋值为24,同样元素b未初始化
4. 之后我们分别打印了t1和t2成员的地址
接下来我们编译运行,看下结果:
可以看到结构体t1的元素b未初始化,是一个随机值(因为我们定义的t1是局部变量,定义在栈上,如果不清楚什么是栈,什么是堆,以及它们的特性,可以查阅我之前的文章~)。
而共用体t2元素b未初始化, 但是它的值与元素a居然相同(这不是凑巧哦,不相信的小伙伴可以自己测试下,当然前提是a的初始化的值不能超过元素b的类型值域, 同时这里会涉及大小端的问题,这个之后会详细分析)。同时可以看到结构体t1的元素a和b的地址是不同的, 而共用体t2的元素a和b地址是完全一致!相信到这里大家能基本了解了共用体的特性: 成员之间共用一块内存空间,只是解析方式不同。
共用体的大小
经过上面的讲述,大家知道了共用体的成员其实是共享了一块内存空间,哪么当我们顶一个共用体类型时,它实际占用的内存空间是多少呢?
我们先举一个简单的例子:
#include <stdio.h>union test{ int a; char b; };int main(void){ union test t1; //打印共用体成员的数据类型大小 printf("sizeof(int) = %d.\n", sizeof(int)); printf("sizeof(char) = %d.\n", sizeof(char)); //打印共用体大小 printf("sizeof(union test) = %d.\n", sizeof(union test)); return 0;}
编译运行结果:
可以看到共用体变量t1的内存大小为4字节, 即原则上,共用体大小取决于占据最多内存的成员的长度。需要注意这里用的“原则”一词,因为有时候需要考虑内存对齐问题。 我们通过以下例子来加深理解:
#include <stdio.h>//通过__attribute__指令设置1字节对齐__attribute__((aligned(1)))struct mystruct{ char a; int b; int c; int d; int e; double f; char g; short h; double i; float j; }__attribute__((packed));//通过__attribute__指令设置1字节对齐__attribute__((aligned(1)))union test{ int a; char b; float c; double d; struct mystruct my1;}__attribute__((packed));int main(void){//定义了共用体变量t1 union test t1; //打印了结构体大小 printf("sizeof(struct mystruct) = %d.\n", sizeof(struct mystruct));//打印共用体大小 printf("sizeof(union test) = %d.\n", sizeof(union test)); return 0;}
分析:
1. 首先我们定义了结构体类型mystruct, 并使用__attribute__指令设置为1字节对齐
2. 定义了共用体类型,其中一个成员是上面定义的结构体mystruct类型, 同时也使用__attribute__指令设置为1字节对齐
3. 定义了共用体变量t1
4. 分别打印了结构体mystruct类型大小,和共用体test 类型大小
OK, 编译运行:
我们可以看到共用体的大小就等于成员my1(结构体类型)的大小,再次验证了上面的结论。
共用体的访问方式
上面我们举得的例子都是使用下标式访问共用体成员,还是和数组,结构体一样, 下标式访问知识编译器提供的一种语法糖, 方便开发人员使用和理解, 但是我们需要了解其本质: 共享一块内存,只是解析方式不同。 因此我们可以通过指针方式来访问,这也是真正理解共用体的判断标准。
#include <stdio.h>union test{ int a; float b;};int main(void){ union test t1; //下标式访问 t1.a = 1123477094; printf("t1.b = %f.\n", t1.b); //指针式访问 int a = 1123477094; printf("指针方式: t1.b = %f.\n", *(float *)&a); return 0;}
编译运行:
从结果再次验证共用体实质:共享一块内存,只是解析方式不同。
总结
通过以上分析,我们了解了共用体的实质,如何定义和使用,以及与结构体的区别等。 之后我会讲解共用体的应用场景,尤其是如何使用共用体测试系统大小端,这也是面试和笔试中出现的概率非常高的题目,如果你对大小端的概念不是很清楚,或者想了解有哪些办法测试系统的大小端,欢迎转发,收藏,关注,后续内容更加精彩哟~
标签: #c语言共用体结构体