自定义类型
一、结构体
1.1 结构体的声明
用通讯录的例子展示:
structPeoInfo{char name[10];//姓名int age;//年龄char sex[6];//性别char tel[13];//电话char addr[20];//地址}p1;//p1是全局变量
这是普通的声明,而还有另一种声明的方式:匿名结构体的声明。
struct{char name[10];//姓名int age;//年龄char sex[6];//性别char tel[13];//电话char addr[20];//地址}p1;//p1是全局变量
匿名结构体只能在声明的后边创建变量,其他地方不能用。
struct{int a;char b;float c;}x;struct{int a;char b;float c;}a[20],* p;intmain(){
p =&x;return0;}
要注意这种代码是不合法的,编译器会默认把上面两个类型当成不同的类型。
1.2 结构体的自引用
structNode{int data;structNode next;};
有人可能会这么写。但是这样会出现问题:无法计算Node的大小。所以正确用法:
structNode{int data;structNode* next;};
1.3 结构体变量的初始化
structNode{int data;structNode* next;}n1;structNode n2;
两种定义方法都可以。
初始化要使用{},含有嵌套的就在{}里加{}。
structA{int a;int b;};structB{int c;structA a;};intmain(){structA a ={1,2};structB b ={1,{1,1}};return0;}
1.4 结构体的内存对齐和大小计算
里面有详细介绍和练习:
结构体/联合体大小的计算
1.5 为什么存在内存对齐❗️❗️
1️⃣平台原因
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2️⃣性能原因
数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
假设在32位机器(一次访问四个字节)访问a:
总体来说:
结构体内存对齐是拿空间换时间的做法。
所以为了节省空间,我们在设计时要:让占用空间小的成员尽量集中在一起。
二、位段
2.1 位段的概念
structA{int _a :2;int _b :5;int _c :10;int _d :30;};
可以看出他跟结构体的区别有两点:
1)位段的成员必须是 int、unsigned int 或signed int (也可以是char类型)。
2)位段的成员名后边有一个冒号和一个数字。
2.2 位段的大小计算
首先要知道冒号后面的数字是什么意思:
int的大小是4个字节,后边的2表示它只需要两个比特位。所以后边的数字不能超过他自己类型的范围。
计算方法:
要注意没用完的空间被浪费了
structA{int a :1;char b;};
这个位段的大小也为8,因为要考虑内存对齐而且不同的数据类型不能用一块空间。
2.3 位段的内存分配
structS{char a:3;char b:4;char c:5;char d:4;};structS s ={0};
s.a =10;
s.b =12;
s.c =3;
s.d =4;
2.4 位段的跨平台问题
1) int 位段被当成有符号数还是无符号数是不确定的。
2) 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题)。
3) 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
4) 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。
三、枚举
3.1 枚举类型的定义
enumDay//星期{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
像星期,颜色这种有限的东西可以用枚举。
enum Day
是枚举类型{}内叫枚举常量。
3.2 枚举的优点
1) 增加代码的可读性和可维护性
2) 和#define定义的标识符比较枚举有类型检查,更加严谨。
3) 防止了命名污染(封装)
4) 便于调试
5) 使用方便,一次可以定义多个常量
3.3 枚举的使用
enumDay//星期{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
其实这些枚举常量都有值,从0开始,往后+1。也可以自己赋值:
enumDay//星期{
Mon =1,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
这样就是从1往后加。后面可以直接用枚举变量来赋值
四、联合体(共用体)
4.1 联合体的定义
//联合类型的声明union Un
{char c;int i;};
4.2 联合体的特点
因为联合体是共用一块空间,所以改变其中一个变量另一个变量也会改变。
4.3 联合体的大小计算
里面有详细介绍和练习:
结构体/联合体大小的计算
版权归原作者 命由己造~ 所有, 如有侵权,请联系我们删除。