一. 初识结构体
1. 结构体的构成
结构体关键字+结构体标签
{
结构体成员
} 结构体变量(可不写);
//结构体关键字+结构体标签{结构体成员} 叫结构体类型
//创建结构体变量有2种方法:一种是创建结构体类型时创建变量(左上角形式)
//另一种是结构体创建好后用 结构体关键字+结构体标签+要创建的结构体变量
//形式来创建
2. 匿名结构体:隐藏结构体标签
结构体关键字
{
结构体成员
} 结构体变量(必须写);
//这种结构体也就只能以左边形式创建变量,这也意味着靠 结构体关键字+结构体标签+要创建的结构体变量
//形式创建变量是不可以的,因为没有结构体标签,如果该种结构体你只想用一次,那么使用匿名结构体比较合适
3. 结构体的意义解读
struct
{
int a;
char b;
float c;
} a[20],*p //数组a中有20个元素,每个元素都是一个结构体;
//p是一个指针,存放的是结构体的地址;
4. 结构体的引用:引用一个结构体要做的事情是获取这个结构体的地址
struct Node
{
int data;
struct Node* next;//存放要引用的结构体的地址
};
5. 结构体类型的重定义
typedef struct Node
{
int data;
struct Node* next;
} Node;
//这段代码的意思为:把结构体 struct Node{int data;struct Node*
//next;}重新取一个名字,取名为Node,这意味着本来创建结构体变量时要
//用struct Node N,此时可以简写为:Node N,两者是等价的
//匿名结构体没办法重定义
6. 结构体指针的重定义
typedef struct Node
{
int data;
struct Node* next;
} * pNode;
//这段代码的意思为:把结构体指针 typedef struct Node{int data;struct
//Node* next;} * 重新取名为 pNode,这意味着本来创建结构体指针要用
//struct Node *p,此为可以简写为 pNode p,两者是等价的
二. 结构体内存对齐
对齐规则:1)第一个成员放在偏移量为0的地址处
2)其他成员对齐到对齐数的整数倍数
3)结构体的总大小为最大对齐数的整数倍
4)如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的总体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍
//备注:1)中 偏移量:一个字节相对于起始位置隔了几个字节偏移量就是几,很显然,起始位置偏移量为0;
2)中 对齐数:编译器默认对齐数(vs默认为8)与组成员大小的较小数;
3)中 最大对齐数:每个成员对齐数选出来进行比较,选出最大的,把它当作最大对齐数;
offsetof(结构体关键字+标签,结构体成员名)是用来计算相对于起始位置的偏移量,返回的是无符号整型;
设计结构体时,让占用空间小的成员尽量集中在一起;
修改默认对齐数的方法:
#pragma pack(想填的整数)(此句后默认对齐数被修改成 想填的整数)
.........
#pragma pack()(此句后对齐数被修改为默认值)
三. 位段:以位为单位来定义结构体中的成员变量所占的空间
1)位段的成员必须是 int,unsigned int 或 signed int
2)位段的成员名后面有一个冒号和一个数字:
int _a : 2; // 开辟一个整型空间,把这个整型空间的2位空间给_a,剩下的空间分配给后面的变量,后面的变量也不一定就是紧紧挨着变量_a放的,反正最终肯定是节省了空间
注意:
位段是不对齐的,因为位段本身是节省空间的;
位段设及很多不确定因素,位段是不跨平台的,注重可移植的程序因避免使用位段;
位段被当成有符号数还是无符号数是不确定的;
位段中最大位数的数目不能确定(有的平台是16位一个int,有的平台是32位一个int);
位段中的成员在内存中是从左向右分配还是从右向左分配尚未定义;
当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段的剩余空间时,是舍弃剩余的位段还是利用,这是不确定的,即上例中所说的 “后面的变量也不一定就是紧紧挨着变量_a放的,反正最终肯定是节省了空间”.
四. 枚举
枚举结构形式:
enum col
{
Red = 1,
Green = 5,
Blue = 9
};
//Red = 1为初始化,不是赋值,此后Red = 2是不行的,因为此时是赋值
五. 联合(又叫共同体):共同体指共用同一块内存区域,所以对于联合体内的成员,一般同一时间只会使用一个
共同体:共同体指共用同一块内存区域,所以对于联合体内的成员,一般同一时间只会使用一个
说明:共用同一块内存区域 是指从开始位置共用,即共同体内成员起始位置一样;
联合体的关键字是 union,如:
union Un
{
char arr[5];
int i;
};
联合的成员是共用同一块内存空间的,这样一个联合成员的大小,至少是最大成员的大小,因为联合至少有能力保存最大的那个成员,当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍;
联合体大小的计算:需要对齐计算:以上面的例子为例,“char arr[5]; ”,5个char类型,char大小为1,vs默认对齐数为8,所以最终对齐数为1,偏移量为0处开始放5个char,“int i;”,int大小为4,vs默认对齐数为8,所以最终对齐数为4,共同体共用他同一块内存(起始位置相同),所以偏移量为0处开始取4个字节放,最终arr[5]与i一共占用5个字节空间,5不是最大对齐数4(1与4比较得出)的整数倍,所以最终联合的空间为8个字节。