##结构体类型创建
定义:结构体是一个聚合数据类型;将相同或不同类型的元素放到一起,结构体内存布局和数组基本一致,结构体内部第一个成员变量的地址最低;
####结构体声明
struct A
{
int a;
char b[20];
short c;
};//分号不能丢
上面一段代码就可以被称为一个结构体,struct A为结构体名,{ }内为成员变量,}后必须加;
其他形式的结构体声明
1.匿名结构体声明:用于结构体只使用一次是用匿名声明
struct
{
int a;
char b;
float c;
}x;//x 为结构体变量
struct
{
int a;
char b;
float c;
}a[20],*p;//a[20]为结构体数组,p为结构体指针,指向结构体
2.类型重定义结构体声明
typedef struct A
{
int a;
char b;
}Node;//Node为结构体名,struct A也为结构体名进行了类型重定义
结构体自引用
首先看错误的声明方法
struct Node
{
int data;
struct Node next;
};//结构体一被使用,就会一直创建结构体,会崩溃
所以应该这样声明
struct Node
{
int data;
Node* next;//结点
};
结构体定义
struct A
{
int a;
char b[20];
short c;
};//分号不能丢
struct A p1;//定义d定义结构体
struct A
{
int a;
char b;
float c;
}a[20],*p;//此种方式也为结构体定义
结构体初始化
结构体的初始化与数组的初始化完全一致
结构体可以被整体初始化,但不能被整体赋值
都用{}来初始化,{}里面放不同类型
//例子
struct A
{
int a;
char b[20];
short c;
};//分号不能丢
struct A p1={1,{a},2};
//例子
struct A
{
int a;
char b[20];
short c;
} p1={1,{a},2};
结构体内存对齐
方法:
1.第一个成员变量与结构体变量偏移量为0地址处(第一个成员变量的地址=结构体地址)
2.其他成员变量要对齐到某个数字(对其数)的整数倍的地址处。
对齐数=编译器默认的对其属与该成员大小 的较小值 。(在vs中对齐数为8,Linux为4)
对齐:存放该变量的起始偏移量要整除改变量的对齐数(通常是能整除该变量的最小整数)
3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4.如果嵌套了结构体,嵌套结构体对齐到自己的最大对其属的整数倍,结构体的整体大小就是所有最大对齐数(内嵌套结构体的对齐数)的整数倍。(一个结构体对齐数,内部最大对齐数)。
为什么要内存对齐?
内存对齐是一种用空间换取时间的行为的
修改默认对齐数操作
#pragma pack(8)//设置最大对齐数
struct A
{
char c1;//1+3
int i;//4+4
char c2;//8+1+3
};//分号不能丢
#pragma pack()
#pragma pack(1)
struct B
{
char c1;//1
int i;//1+4
char c2;//5+1
};//分号不能丢
上面两段代码 成员变量类型完全相同,struct A 大小是12,struct B大小是6
结构体传参
结构体传参推荐传结构体的地址,而不是传结构体
因为函数传参时会拷贝一份临时变量,如果穿结构体就会直接拷贝整个结构体浪费空间;
如果传入结构体地址,就会拿一个结构体指针来接收;指针在32位平台下,都是4个字节,会大大节省了空间
位段,位段计算机大小
位段用于计算机网络,定义协议
1.位段的成员必须是int,unsigned,char
2.位段的成员变量名后边有一个冒号和一个数字。
和结构体相比,位段可以达到同样的效果,但可以很好的节省空间,但有跨平台问题
struct A
{
char a:3;
char b:4;
char c:5;
char d:4;
};
struct Ss={0};
s.a=10;
s.b=12;
s.c=3;
s.d=4;
内存分配
枚举+联合
枚举 --------列举。把可能的取值----列举
如 一周七天可以列举,一个物体有几个颜色也可以列举
enum Day
{
Mon,//里面的成员变量都是枚举常量
Tues,
Wed,
Thur,
Fri,
Sat,
Sun,
};
enum Day day=Fri;
day=5; //也可以 但是无意义
枚举常量的值默认从0 开始,一次递增,如果赋初值,则从初值处一次递增;
联合(共用体)
联合是一种特殊的自定义类型,有一系列成员变量,特征是这些成员共用一块空间
特点:联合体所有成员共用一块空间 ,所以所有成员变量的地址都是一样的都为联合体的地址;
union Un
{
char c;
int i;
}
union Un un;
printf("%d\n",sizeof(un));
联合体任然要遵循内存对齐
1.联合体的大小至少是最大成员的大小;
2.当最大成员不是最大对齐数的整数倍时,就把联合体扩大到最大对齐数的整数倍;