• 由浅到深认识C语言(13):共用体


    该文章Github地址:https://github.com/AntonyCheng/c-notes

    在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址:https://blog.csdn.net/AntonyCheng/article/details/136555245),该模板集成了最常见的开发组件,同时基于修改配置文件实现组件的装载,除了这些,模板中还有非常丰富的整合示例,同时单体架构也非常适合SpringBoot框架入门,如果觉得有意义或者有帮助,欢迎Star & Issues & PR!

    上一章:由浅到深认识C语言(12):位段/位域

    13.共用体

    13.1.结构体和共用体的区别

    • 结构体:

      每个成员都有自己独立的空间;

      struct data{
          char a;
          short b;
          int c;
      };
      
      • 1
      • 2
      • 3
      • 4
      • 5

      画图如下:

      ccccbba(null)
    • 共用体(联合体):

      所有成员共享同一份空间,空间大小由占内存最大的成员所决定;

      union data{
          char a;
          short b;
          int c;
      };  //a b c成员共享同一份空间
      
      • 1
      • 2
      • 3
      • 4
      • 5

      画图如下:

      c(b)(a)c(b)cc

      共用体所表示是可以被不断刷新的,它就像是比较万能的一种数据类型,可以同时表示多种基本数据结构,甚至是数组等引用类型:

      //普通数据类型
      #include
      
      typedef union data{
      	char a;
      	short b;
      	int c;
      }DATA;
      
      int main(int argc, char* argv[]) {
      	DATA data;
      	printf("sizeof(data) = %d\n", sizeof(data));
      	data.b = 1;
      	data.a = 2;
      	data.c = 4;
      	printf("%x\n", data);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

      打印效果如下:

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      //引用数据类型
      #include
      
      typedef union data{
      	char a;
      	short b;
      	int c;
      	int arr[5];
      }DATA;
      
      int main(int argc, char* argv[]) {
      	DATA data;
      	printf("sizeof(data) = %d\n", sizeof(data));
      	data.b = 0;
      	data.a = 0;
      	data.arr[0] = 3;
      	data.arr[1] = 2;
      	data.arr[2] = 1;
      	data.arr[3] = 1;
      	data.arr[4] = 2;
      	printf("%x\n", *data.arr);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22

      打印效果如下:

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      这里打印出来的总大小为data.arr的大小,而取 * 是读取的该地址的首元素,此时就是数组的第一个元素;

      **案例:**思考下例打印结果;

      #include
      
      typedef union data{
      	char a;
      	short b;
      	int c;
      }DATA;
      
      int main(int argc, char* argv[]) {
      	DATA data;
      	data.b = 10;
      	data.a = 20;
      	data.c = 30;
      	printf("%u\n", data.a+data.b+data.c);
          //由于
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      打印效果如下:

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

      结果不可以看作是最后一次赋值决定了成员的取值,而是因为 30 这个数据太小了,一个字节都能装下,所以最小的一个数据类型 char 都能装下,所以可以被覆盖,具体解释出现在下一小节;

    13.2.共用体成员提取

    共用体的空间大小由最大的成员决定,共用体虽然共同拥有一份空间,但是从空间读取的字节数是由成员自身类型决定的,即这是一种内存覆盖的提取方法,示例如下:

    #include
    
    typedef union data{
    	char a;
    	short b;
    	int c;
    }DATA;
    
    int main(int argc, char* argv[]) {
    	DATA data;
    	data.c = 0x01020304;
    	data.b = 0x0102;
    	data.a = 0x01;
    	printf("%#x\n", data.a+data.b+data.c);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    打印效果如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    从十六进制换算来看,并不是简单的赋值操作,原理如下:

    首先我们将三个数按照内存中的排布方式给列出来:

    04030201
    0201
    01

    按照赋值的顺序依次覆盖内存:

    01010201

    然后在这段内存上取值,画图如下:

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    下一章:由浅到深认识C语言(14):枚举

  • 相关阅读:
    1747. 应该被禁止的 Leetflex 账户
    5年经验之谈 —— 性能测试如何定位分析性能瓶颈?
    梯度下降法
    golang 协程一些小问题 golang 协程一些小问题,以及解决办法
    增益与功率:lg|dB|dBm|mW计算
    ParameterizedType类型设置默认值
    仅用61行代码,你也能从零训练大模型
    系统架构设计专业技能 ·操作系统
    动态规划无效总结--回文子串,最大子数和
    {大厂漏洞 } OA产品存在SQL注入
  • 原文地址:https://blog.csdn.net/AntonyCheng/article/details/136774711