结构体;struct
结构体声明,声明一个结构体的 类型
这些都是一个结构体的声明,这是一个类型,还没有创建变量
里面的都是结构体类型的成员。
创建变量
b3,b4为创建类型时同时创建变量
也能创建成数组
匿名创建变量
匿名创建变量时,只能在声明的同时创建变量
类型重命名
将 类型 struct Node 重命名为 Node(这也是类型),所以 类型 Node 等于 类型 struct Node
自引用
在一个结构体中存放着与自己类型相同一个结构体指针,叫自引用
1、不能是匿名结构体
2、里面不能去除
结构体内存对齐
举例变量
上规则:
规则一、第一个成员
假设创建的那个结构体变量的起始地址在红线处,那么这个地址的偏移量为 0,下一个地址偏移量为1。
结构体的第一个成员就放在起始位置。从起始位置算这个成员所需要多大的空间。
规则二、其他成员
放在整数倍对齐数(成员的大小)的偏移量地址处,对齐数与默认对齐数(默认对齐数是:8)比较谁小要哪个
VS才有默认对齐数,其他的环境可能没有,没有就是本身大小。
int 类型对齐数是4,直接看谁的偏移量是4的倍数就能存了(前提是你选的没有被占用,所才是4的倍数)
规则三、总大小的计算
总大小为最大对齐数的整数倍,成员之间相比较得出最大对齐数。总大小就不看偏移量了,直接算需要多少空间,
上总结:
第一个成员不用管,其他成员看对齐数(对齐数与偏移量挂钩,决定了放的位置),总大小看最大对齐数与目前所占空间。
规则四、结构体嵌套
结构体要点:这个结构体的 对齐数 ,嵌套结构体的对齐数就是它自己内部最大的那个对齐数。
只需放在这个对齐数(整数倍)的相应偏移量地址就行。
总大小不变,找最大对齐数(规则上面说的是所有对齐数的倍数,意思就是如果有奇数(一除外),总大小还得为公倍数),目前貌似没有发现有奇数的对齐数。
如果想省内存,应把占用空间小的成员挨着放
修改默认对齐数
#pragma pack ( 1 ),括号里为你想修改的大小,放上面目的是修改下面这个结构体的对齐数。
#pragma pack ( ),下面的括号里为空意思取消修改默认对齐数,它只能影响之后的代码,不会影响上面。
结构体位段
位段的成员必须是 int 类型(有符号无符号都行)
表示方法:在变量名的后面加冒号再加数字
后面的数字,表示只给这个 _a 变量分配 2个二进制位的空间
位段的内存分配
2、在开辟空间的时候,还是按照类型开辟的,只不过分配的空间,一个成员没用完会给到另一个成员使用,所以位段的内存占用会小一点。
举例模板
首先,先开辟一个字节的空间,然后给 a 分3 位,VS的分配规则是从右往左分配(其他编译器可能不一样),如图所示。
空间够用再给 b 分 4位
不够下一位放就浪费掉,再开辟一个字节放 c
只需三个字节就分配完了
在存值的时候,如果存不下就截断
就只有10是存不下的10至少得4位二进制才能表示所以截断后三位
存入内存
位段没有倒着存就是想象出来的顺序存放的。
这三个字节是由低向高开辟出来的,并且是连续的,而且存放的数据根本不会超过一个字节,所以也不会倒着放。
小端存储的逻辑就是,一个字节我放不下你给的数据,我就会把小的那一部分放低地址,大的那一部分放高地址
位段使用注意事项
计算机里面为一个字节分配一个地址,那么就会存在一些成员的起始并不在第一位,这个成员也就没有地址。也不能进行对他取地址这样的操作。
VS开辟的空间是从地址向高低开辟的所以没有倒着放(不完全对)不完全的原因就是因为是小端存放从低地址往高地址放。又或者是数据没有超过一个字节所以不会有顺序问题(这个没问题)没超过一个字节的数据不会逆置。
再有就是char 应该不存在着大小端的问题
联合体
联合体与结构体的区别,联合体只给最大( )的那个成员开辟空间所有成员共享这一块空间
联合体公用一块空间,也就是说,只需修改一个成员的值,这块空间就会发生改变,(并且开辟空间的时候也是从低地址向高地址开辟)
联合体的总大小
联合的的总大小也得看对齐数,上面说到为最大的成员开辟空间,这个char 数是最大的成员,开辟5个字节的空间,也能放的下 int,但是总空间要对其成员的最大对齐数的倍数,char 的对齐数是1,尽管他是一个数组,但每个元素是char ,数组只看元素的对齐数就行。所以这个联合的大小就是8个字节
又或者,你这样算也行,先找最大对齐数,再看最大的成员需要多大的空间,然后你再算这个对齐数的多少倍能放的下这个最大的成员。
联合体看大小端
创建一个联合体变量,空间4个字节,然后修改 i 给他赋值 1,如果是小端存放这个1就会放在地址处,大端放高地址。然后返回 c, c的起始位置也是u的起始地址,包括 i 他的起始地址也是。如果是大端,这个1就会放在高地址处(但是又有个问题就是大端机器的开辟空间不会也是从高低地址往地址开辟吧,那不就没啥区别),返回 c ,如果是小端 c就是1,大端就是0.
枚举
概念:一个类型的成员能够一一列举出来
在用枚举类型创建变量,赋值的时候只能赋值为某个成员,每个成员用逗号隔开。
第一个成员默认值是0,第二个就是1,依次递增,但如果你修改了某个成员的初始值,那么递增就从修改那里开始改变