目录
一、结构体概念
概念:是一种复杂数据类型,多个基础数据类型合并到一起。
结构体变量中的成员变量,只有在初始化的时候可以通过赋值进行初始化,定义完毕后不能使用赋值进行整体的成员变量初始化。
例如:描述一群狗
struct dog_t{
int size;
int weight;
char name[10];
char voice[20];
};
typedef struct dog_t{
int size;
int weight;
char name[10];
char voice[20];
}_dog_t, *pdog_t;//结构体指针类型
ps:指针的步长就是所指向类型元素的大小,结构体类型指针的步长就是结构体类型大小
二、结构体的自引用
struct dog_t{
int size;
int weight;
char name[10];
char voice[20];
struct dog_t dog2//不可以,结构体类型大小不固定,会一直循环包括自己
struct dog_t *dog1;//可以,指针大小固定,先声明、后定义
};
typedef struct dog_t{
int size;
int weight;
char name[10];
char voice[20];
struct dog_t dog2//不可以,错误
struct dog_t *dog1;//可以,正确
}_dog_t, *pdog_t;
注意点:
typedef struct dog_t{
int size;
int weight;
char name[10];
char voice[20];
dog_t *dog2//不可以,错误
struct dog_t *dog1;//可以,正确
}_dog_t, *pdog_t;
三、结构体变量定义
struct dog_t dog1 = { 120, 20, "大黄", "汪汪汪" };
struct dog_t dog3[10] = { { 120, 20, "大黄", "汪汪汪" } };
struct dog_t dog2;
_dog_t dog3 = { 120, 20, "大黄", "汪汪汪" };
pdog_t dog4 = &dog3;//dog4指针
dog2.size = 10;
strcmp(dog2.name, "蓝猫");
四、结构体内存对齐
当CPU从内存中取数据的时候,数据总线位数是32位,则一次可以从内存中取出4字节数据。但是如果四字节数据从一个存储颗粒中取出,则是串行的。为了提高效率,多加几颗存储颗粒,从每个存储颗粒中取出一个字节,就可以并行同时取出四字节数据。因此有些硬件平台CPU只能从指定地址取出指定大小数据。
(一)内存对齐原因:
1.不是所有的硬件平台都支持随意访问。
2.提高结构体成员访问效率。
(二)内存对齐规则:
1.在任何一个平台下都有默认对齐数。
2.结构体每个成员变量又有一个自己独立的对齐数,就是成员变量类型的大小。
3.实际成员变量的对齐数是成员自己独立的对齐数与默认对齐数中较小的那个。
4.每个成员变量都应该对齐到这个对齐数的整数倍处。
5.结构体的总大小应该是实际最大对齐数的整数倍大小,不足补位。
6.如果成员变量也是结构体变量,则这个结构体变量的对齐数,为自己结构内部的实际最大的对齐数。
例:由于结构体的总大小应该是实际最大对齐数的整数倍大小,不足补位。故而结构体的总大小是4的整数倍。所以结构体的总大小16,补位2位。
(三)默认对齐数的修改:
#pragma pack(n) //将默认对齐数设置为n
#pragma pack //还原默认对齐数
修改默认对齐数的原因:涉及网络通信,将一个结构体变量(一块连续的内存数据)发送给另一个主机,如果两个平台对齐数不一致,在进行内存中数据解释的时候就会出现问题。
(四)结构体位段:
使用位段,member:n 表示使用指定空间中n个比特位存储数据,并且多个位段可以合并占用同一个存储空间,从低位向高位存储。
1.位段存储数据过大会产生截断
2.位段必须是整型不能是浮点型
3.使用位段原因:可以节省空间
4.位段的存储方式:从低位逐位存储。第一个位段剩余空间不够存储第二个位段,则会为第二个位段新开空间存储
例题:
struct student_t
{
int sn;
int sex:1;//0-男;1-女;只占了一个字节空间的1个比特位
int pos:2;//0-普通;1-班长;2-副班长只占了一个字节空间的2个比特位
float score;
};