C结构体、共用体、枚举

一、结构体

(1)类型声明

结构体类型声明

注意,这一步操作只是声明了一个类型struct student,不占据栈空间或堆空间。

只有当使用struct student这个类型,定义变量的时候,才会占据空间。且声明的最后一定要加上分号。接下来进行结构体变量定义和赋值。

赋值

结构体数组(数组每个元素都为struct student类型的结构体)

结构体数组定义

结构体数组赋值与输出

赋值与输出

结构体变量的大小:

这时候我们如果想知道这个结构体的大小,不能直接按照他的成员类型一个一个加起来那样计算,这样计算往往都会出错。

这就涉及到了地址对齐的概念,为了能够减少取数据的次数,计算机采用了空间换时间的方法,就是地址对齐,让不足四字节的数据(如char、short),补齐成四字节大小,方便数据取入到寄存器,避免了后续数据没有对齐而导致本能一次取出的数据分为多次才可取出的情况,提高数据存取效率。

上图中的结构体,如果我们自己算大小的话,其实是4+20+1+4+4+30=63字节,但是经打印发现其实是68字节。如图

其实就是对结构体中的char sex补齐了三字节,对char addr[30]末尾补齐了2字节,所以最终大小为68字节。

根据这个地址对齐的原理,我们以后声明结构体时,可以采用定义结构体把小字节定义在一起,放到结构体最后的方式,这样可以更紧凑的利用空间,避免过多的地址对齐。

(2)结构体指针

指针访问结构体成员的两种方法

结构体指针的偏移、自增操作

这个自增操作可分为两步:num = p->id; (p->id)++;故如果对num和p->id进行打印,应该分别是1001和1002,打印验证一下。

这里仅仅是该结构体成员id的一个自增操作。

再看下面的例子,

依旧分为两步:num = p->id; p++; 

这回便是指针变量p的自增操作了,即指针将进行偏移,偏移的步长是多少呢?答案是步长为该结构体的大小。如图

p+1相对于p偏移了68字节,正好是一个结构体的大小。

故应当是从arr[0]的位置,偏移到了arr[1]的位置,即num的输出应为1001,而p->id为1003。打印验证。

(3)typedef的使用(给结构体起别名)

从前面的小例子中,可以看到我们定义的结构体struct student类型。每次定义结构体变量的时候,都需要写上struct student类型名,而这么长的类型名对我们的使用也是非常的不方便,所以就轮到typedef出场了。如图

给结构体类型起别名

上图中的用法是连续起了两个别名,stu是结构体类型名,而pstu是结构体指针类型名。

这样,以后再此定义该结构体变量,就不需要用struct student类型来定义结构体变量了,而是只用stu定义结构体变量即可

而pstu等价于struct student1*,以后要定义结构体指针时,可直接用pstu类型名来定义。如pstu p;(p即为结构体指针),如下图。

注意不要与下面的用法混淆!!!

快捷定义结构体变量

没加typedef的时候,这个s是结构体变量,可直接使用,用来访问结构体成员。

前面加了typedef时,这个s是代替了struct teacher的结构体类型,是用来定义结构体变量的,一定要注意区分。

(4)typedef和define

define是在预处理阶段起作用。故使用时前面要加#号,注意后面不加分号

typedef是在真正编译的时候起作用,生成一个新的类型名,使用时注意前面没#号,后面有分号。

两种用法效果相同,都是使用INTEGER代替了int。

这里的INTEGER显示橙色高亮是因为上图使用typedef和define时,#define在下面,由于遵守就近原则,所以下面这个INTEGER其实由#define进行的别名替代。故typedef和#define不要一起使用,使用一个即可。

基本了解了结构体的使用方法后,就可以搭配指针,适当进行一些数据结构的编写了,如链表、树等。

二、共用体

共用体,顾名思义,即是共用体内各个成员共同使用该空间。

(1)不同于结构体的方面

接下来罗列出共用体和结构体不同的地方:

 1.共用体一般用于满足某个接口,可能会接收不同类型的参数的需求。

 2.共用体的大小就是该共用体中最大的成员的大小

 3.同一段内存可以用来存放几种不同类型的成员,但在每个瞬间只能存放其中一种,而不能同时存放几种。

 4.共用体变量中起作用的成员是最后一次存入的成员,存入一个新成员后,原来起作用的成员就失去了作用。

 5.共用体变量的地址和他的各成员的地址都是同一地址。如果共用体变量a的起始地址为1000,那么共用体内成员i,ch,f的起始地址均为1000.

 6.不能对共用体变量名赋值,也不能企图引用共用体变量名来得到一个值。

(2)共用体类型和共用体变量的定义

共用体类型的定义和共用体变量的定义操作都是一致的。

对于其成员的赋值也和结构体一直,如图

不过要注意,与结构体不同的是,结构体如此赋值后,每个成员都被赋了值,而共用体因为是成员共用这一段空间,并不是共存的关系,所以此时共用体中起作用的成员只有d.f,即只有d.f被成功赋值了。

进行断点分析打印展示。

打印

可以看到,每当一个成员被赋值的时候,其他的成员便失效了。

(3)共用体大小

只与共用体中最大的成员有关,大小与其中最大的成员相等,即如上面定义的共用体,大小就是4字节。

如果对成员进行更改,将int改为long,则大小变为8字节。

最后说一句,共用体类型可以出现在结构体类型定义中,也可以定义共用体数组;结构体可以出现在共用体类型定义中,数组也可以作为共用体的成员。这点共用体和结构体完全一致。

三、枚举

假如我们想要星期日到星期六表示数字0~6(即星期日==0,星期一==1...类推),以此便捷地表示星期几。

如果使用#define的话,需要写七句代码分别定义。这时候我们就可以使用枚举了。

枚举就是将变量的值一一列举出来,变量的值只限于在所列举的值的范围内。

(1)声明枚举类型

声明类型

枚举元素作为常量是有值的,C语言编译时,按定义的顺序使他们的值为0,1,2........如图

打印

如果在声明时,令sun=5,则后面的元素都跟着依次累加。

要注意,C语言在编译时对枚举元素是按常量处理的,故称枚举常量,因为他们不是变量,所以不能对其赋值。

(2)定义枚举变量

枚举值可以用来做判断和比较。

你可能感兴趣的:(C结构体、共用体、枚举)