
目录1.联合体声明定义1.联合体的特点1.联合体的内存大小4.联合体与结构体的对比5.联合体判断编译器的大小端6.枚举类型的声明7.枚举类型的优点8.枚举类型的使用前言今天我们又来学习一种自定义类型联合体那么什么是联合体和枚举呢接下来我们就来学习学习。联合体(也可以成为共用体)联合体就像一个一个结构一样就好像结构体都是由多个成员组合而成这些成员可以是不同的类型关键字union特点编译器只为最大的内存分配空间所有成员共用一块内存空间给联合体内任意一个成员赋值其他成员的值也跟着发生改变。1. 联合体的声明定义接下来演示联合体的声明定义#includestdio.h//联合体类型的声明unionpf{chara;intc;};intmain(){//联合体类型定义unionpf opp{0};return0;}以上就是我们联合体简单的声明和定义。 返回目录2. 联合体的特点联合体的成员是共用一块内存空间的联合体的内存大小至少是最大成员体的内存大小只有这样才能保证每一个联合体成员都能够存得下。我们通过Vs调试窗口内存来探究他的结果代码1#includestdio.h//联合体类型的声明unionpf{chara;intc;};intmain(){//联合体类型定义unionpf opp{0};//打印每个成员的地址printf(%p\n,opp);printf(%p\n,(opp.a));printf(%p\n,(opp.c));return0;}代码2#includestdio.h//联合体类型的声明unionpf{chara;intc;};intmain(){//联合体类型定义unionpf opp{0};opp.c0x11223344;opp.a0x55;printf(%x\n,(opp.a));return0;}代码1我们发现了他们三个的结果都是相同的第一个地址。我们再看看他opp.c的内存和opp.a的内存地址。代码2我们发现了原本opp.c这个位置原本上应该存放的是0x11223344这里的44被opp.a里面的0x55给占用了。从结果上看我们得到的地址都是相同的地址这就说明了联合体每个成员的内存大小都是共用的。联合体共用内存情况4个字节分别对应着4个地址。 返回目录3. 联合体的内存大小那么我们联合体的内存大小是怎么算的呢联合体的大小最小为最大成员的内存大小。当联合体中最大内存成员的大小不是最大对齐数的整数倍的时候就要对齐到最大对齐数的整数倍。例如//计算下列结构体的大小。#includestdio.hunionpf1{chara[5];intc;};unionpf2{shorta[7];intc;};intmain(){printf(%zu\n,sizeof(unionpf1));printf(%zu\n,sizeof(unionpf2));return0;}结果为什么会是这个结果呢我们来分析一下。 返回目录4.结构体与联合体的对比那么结构体和联合体有什么区别呢structS{charc;inti;};unionUn{charc;inti;};#includestdio.hintmain(){structSs{0};unionUn un{0};return0;}我们通过图片可以知道结构体的内存浪费比较大而我们联合体浪费的内存远远没有结构体那么多。当我们结构体里面内存非常多的时候浪费的内存也会不断增多。而我们的联合体采用的是共用内存空间的形式对于内存的利用比较高。总结联合体可以适当减少内存但是当我们给其中一个成员赋值的时候其他成员的值也会发生改变。 返回目录联合体判断编译器的大小端#includestdio.hinttest(){union{//建立一个联合体inti;charc;}un;un.i1;returnun.c;//因为是联合体所以c和i的内存是共用的我们返回char类型的c让他访问一个字节。返回1是小端返回0是大端}intmain(){intrtest();if(r1){printf(小端\n);}else{printf(大端\n);}return0;}我们使用的Vs编译器为小端。 返回目录枚举类型枚举就是一个一个把可能的值给列举出来。就像我们生活中星期一到星期天、月份、颜色、价格等等这些东西给一一列举出来。像这些数字我们就能够使用枚举给他们列出来。在以后写代码过程中避免不了大量的代码代码一多就会出现各种各样的问题。例如以订单为例子 c#includestdio.h//我们用#defind定义了一些毫无关系的常量#defineORDER_PENDING_PAYMENT1#defineORDER_PENDING_DELIVERY2#defineORDER_DELIVERED3#defineORDER_COMPLETED4voidList(intstatus){switch(status){caseORDER_PENDING_PAYMENT:printf(订单待付款\n);break;caseORDER_PENDING_DELIVERY:printf(订单待发货\n);break;case30:printf(订单已发货\n);break;caseORDER_COMPLETED:printf(订单已完成\n);break;default:printf(状态未知\n);break;}}intmain(){List(3);return0;}问题1常量无归类代码量大了后难以管理问题2容易写错值比如把3写成30编译器无法校验问题3无法直观看出这些常量是一组的调用时只能传数字语义不清晰6.枚举类型的声明举例我们上面的例子#includestdio.henumDay{Mon,Tues,Wed,Thur,Fri,Sat,Sun};颜色enumColor{RED,GREEN,bLUE};注意我们每写完一个枚举成员用逗号隔开而不是分号最后一个枚举成员不用添加分号。在枚举成员{ }外面必须添加分号。我们定义的枚举类型的成员可能都是有值的默认从1开始依次加1在声明枚举类型的时候我们可以进行赋值。例如enumColor{RED3,GREEN4,bLUE6};当我们进行赋值完成后在使用过程中就类似#defind定义常量如果只对第一个进行了赋值那么后面的就会在第一个的基础上加1。enumColor{RED9,GREEN,//这里就会变成10bLUE// 这里就会变成11}; 返回目录7.枚举类型的优点我们知道了#defind也能定义常量为什么还会有枚举呢我们就要学学枚举的优点了。优点增加我们代码的可读性和可维护性#define 定义的常量是全局的无归属关系易命名冲突。相比较#defind我们的枚举有类型检查更加严谨。枚举变量本质是整型变量所以可以用%d输出其数值。枚举成员是编译期常量不能修改便于调试。我们编译器在编译过程中会删掉#defind定义的符号。 返回目录8.枚举类型的使用例如enumColor{RED1,GREEN2,BLUE3};intmain(){enumColorrGREEN;//使⽤枚举常量给枚举变量赋值return0;} 返回目录完