自定义类型:结构体,枚举,联合体
结构体:
结构体是一些值的集合,这些值成为成员变量,结构体的每一个成员都可以是不同类型的变量。
结构体的声明:
struct tag{
member-list;
}variable-list;
例如描述一个学生:
struct Stu{
char name[20];
int age;
char sex[5];
char id[20];
};//必须要有分号
结构体的成员:
结构体的成员可以是标量、数组、指针、甚至是其他结构体。
结构体成员的访问:结构体变量的成员是通过操作符(.)来访问的。
有时候我们得到的不是一个结构体,而是一个结构体指针,那访问如下:
结构体的自引用:
所以我们只能这样定义:
struct Node{
int data;
struct Node *next;
};
因为指针的大小是确定的。
结构体的不完整声明:
struct A{
int _a;
struct B* pb;
};
struct B{
int _b;
struct A* pa;
};
此时我们可以看出,在结构体A中的struct B还没有声明,所以定义会出错。
改正如下:
struct B;
struct A{
int _a;
struct B* pb;
};
struct B{
int _b;
struct A* pa;
};
结构体变量的定义和初始化:
结构体的内存对齐:
如何计算内存对齐:
1、第一个成员在与结构体变量偏移量为0的地址处。
2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的对齐数 与 该成员大小中的较小值。
VS中默认为8;
Linux 中默认为4;
3、结构体总大小为最大对齐数的整数倍。最大对齐数就是结构体的对齐数。
4、如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍。
内存对齐图解:
结构体的传参:
位段:
位段的声明和结构体是类似的,有两个不同:
1、位段的成员必须是:int,unsigned int,signed int
2、位段的成员名后边有一个冒号和一个数字。
比如:struct A {
int a:2;
int b:5;
int c:10;
int d:30
};
A就是一个位段类型,大小为8
位段的内存分配:
1、位段的成员可以是int ,unsignde int,signed int,char类型。
2、位段的空间上是按照需要以4个字节或者1个字节的方式来开辟的。
3、位段设计很多不确定的因素,位段是不跨平台的,可移植的程序应该避免使用位段。
总结:
跟结构体相比,位段可以达到相同的结果,但是可以很好的节省空间,但有跨平台的问题存在
枚举:一一列举
{}内的内容是枚举类型的可能取值,也叫做枚举常量。
默认从0 开始,依次递增,当然在定义的时候,也可以赋初值
enum Color{
red = 1;
green = 2;
blue = 3;
};
枚举的优点:
1、增加代码的可读性 和可维护性;
2、防止命名污染(封装);
3、便于调试;
4、使用方便,一次可以定义多个常量
联合体:
联合体也是一种特殊的自定义成员,特征是这些成员公用同一块空间,所以联合体也叫做公用体。
声明: union Un{
char c;
int i;
};
union Un un;//定义一个联合体
联合体的特点:联合体的成员是公用一块内存空间,一个联合体的大小至少是最大成员的大小。
限于编者水平,难免有不正之处,欢迎指正!