今天给大家分享一下三个自定义类型。
结构体:结构体一些值的集合,这些值称为成员变量。大家在这里可能感觉这和数组怎么有点像,它们最大的区别就在于结构体的每个成员可以是不同类型的变量。
struct tag{
member-list;
}variable-list;
例如我们描述一个学生可以这样表示
struct stu{
char name[20];
int age;
char sex[5];
char id[30];
};
注意一下最后括号后面的分号不能丢。
还有一种不完全声明,即去掉struct后面的名字,例如上面的就是去掉stu。
结构体自引用
下面我写两种调用方法,大家看看哪种方法好一点。
struct Node{
int data;
struct Node next;
};
/*****************/
struct Node{
int data;
struct Node* next;
};
很显然下面一种方法明显较优,因为上面调用是在结构体里面存结构体,而且它的大小无法计算,而下面的方法则是利用指针,使内存变为定值。
结构体在初始化的时候可以直接将所有数据用括号括起来赋值,而在初始化完成后在进行赋值的时候则要利用->或是.访问。
结构体内存对齐
我们已经掌握结构体的基本使用了,现在我们深入探讨一下结构体内存大小问题。
struct s1{
char c1;
int i;
char c2;
};
大家可以在自己的编译器看到这个结构体的大小是12,这就是内存对齐了,接下来问我说一下内存对齐的规则。
1.第一个成员在与结构体变量偏移量为0的地址处。
2.其他变量要对齐到某个数字(对齐数)的整数倍上。
对齐数=编译器默认对齐数与该成员类型大小的较小值
vs默认对齐数为8,Linux没有对齐数
3.结构体的整体大小为对齐数的整数倍。
修改默认对齐数
#pragma pack(8)
括号中数字是多少,默认对齐数就是多少,不填的时候就是默认对齐数。
结构体传参
结构体传参用到->或.区别在于->是指针形式.是普通变量形式。我们在传参的时候最好传结构体地址,以为如果传值就要重新开辟一块空间,如果结构体过大或调用次数过多,会使性能下降。
位段
struct Node{
int a:2;
int b:5;
int c:10;
int d:30;
};
这就是位段,位段的成员必须是整型家族的,开辟空间是按需要四个字节或一个字节开辟的。
与结构相比,位段可以达到同样的效果,不过其存在跨平台问题。
枚举
枚举顾名思义-----列举
比如我们一周有七天可以一一列举
enum Day{
Mon;
Tues;
Wed;
Thur;
Fri;
Sat;
Sun;
};
Mon默认从0开始每次加1,如果自己赋值,则下一个元素在赋值的基础上加1。
联合
union un{
char c;
int i;
};
联合的成员公用一块空间,这样一个联合体的大小最少是最大成员的大小。而他的大小还有一个要求就是要是最大对齐数的整数倍