一、结构体创建
1.结构体是一些值的集合,这些值被称为成员变量,结构体的每个成员可以是不同类型的变量。
struct s{ //结构体名称
int a; //成员变量
char b; //成员变量
float; //成员变量
};
2.结构体内部成员访问
(1)结构体变量访问成员(结构变量的成员是通过点操作符(.)访问的.操作符接受两个操作数。如果s是结构体的具体名称,age 是其内部成员,则s.age就可以访问)。
(2)结构体访问指针变量的成员(定义一个指向该结构体的结构类型的指针ps,如果age是该结构体的内部成员,则(*s).age或者ps->就可以访问)。
3.结构体自引用
在结构中包含一个类型为该结构本身的成员。
struct Node
{
int data;
struct Node *next;
};
二、结构体初始化
struct Point
{
int x;
int y;
}p1; //声明类型同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量同时赋初值
struct Point p3 = { x, y };
struct Stu
{
char name[15];
int age;
};
struct Stu s = { "zhangsan", 20 }; //初始化
struct Node
{
int data;
struct Point p;
struct Node *next;
}n1 = { 10, {4, 5}, NULL }; //结构体嵌套初始化
struct Node n2 = { 20, {5, 6}, NULL }; //结构体嵌套初始化
三、内存对齐
内存对齐原则:
1.第一个成员在结构体变量偏移量为0的地址。
2.其他成员变量对齐到对齐数的整数倍地址,其中VS默认8。
对齐数 = 与成员大小相比,取较小值。
3.结构体总大小为最大对齐数的整数倍。
4.如嵌套其他结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(包括嵌套的结构体)的整数倍。
为什么存在内存对齐
(1)平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址 处取某些特定类型的数据,否则抛出硬件异常。
(2)性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理 器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
struct S {
char a; //从偏移地址0开始 0
char b; //char占一个字节 1
int c; //int占4个字节,与默认对齐数8比较,取4,要从4的倍数的地址开始 4-7
};
//最终大小为8
struct S1 {
char a; //从偏移地址0开始 0
int c; //int占4个字节,与默认对齐数8比较,取4,从4倍数地址开始 4-7
char b; //占一个字节 8
};
//0-8总共9个字节,因为最大对齐数是4,所以总大小要是4的倍数,所以取比9大的最小4的倍数,结果为12
四、位段
位段的成员必须是int、unsigned int、signed int类型
五、枚举
enum Sex
{
MALE,
FEMALE,
SECRET
};
六、联合
联合也是一种特殊的自定义类型 这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以 联合也叫共用体)可以用来判断大小端,以及ip地址转化。
联合体的应用场景:同一块内存空间按照不同方式理解。
union Un
{
int i;
char c;
};
union Un un;