结构体
引入
存储数据: 变量(int a;)、数组(int a[10]),但是现实存储的对象比较复杂,比如:“狗”、“学生”,该怎么 存储到计算机中?使用对象的属性表示一个对象(名词):
学生的属性:
-
学号 => char num[12];
-
年龄 =>int
-
性别 => char Femal/Male
-
学制 = >int
-
姓名 => char name[30];
…
=======> 就需要使用结构体,结构体可以存储多种 不同类型的数据。可以作为一个整体,表示一个对象。
======》允许自己定义组合数据类型
======》 结构体(struct)、共用体(union)、enum(枚举,属于整型)
结构体
定义类型
struct 结构体名字{
成员类型1 成员变量名1;
成员类型2 成员变量名2;
...
};
struct Birthday{
int year;
int month;
int day;
};
//定义了自定义了struct Student这种类型
struct Student{
char name[20];//
int age;
char sex;
char no[20];
struct Birthday day;//出生年月日
};
//1. 结构体名字: 合法的标识符即可,建议第一个字母大写
//2. 成员类型:合法数据类型即可(int char double char[] int* struct struct Student* union enum)
//3.成员变量: 合法的标识符即可
定义变量
struct 结构体类型名 变量名;
struct Student p;//struct Student是一种类型
//p是变量名
结构体变量的空间分配
-
按照定义的成员变量的顺序进行空间分配
-
结构体变量的空间分配是所有成员变量空间分配的总和,可能会因为字节对齐而产生一些填充
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9WCVwIob-1609289927731)(结构体笔记1.assets/image-20201229095957754.png)]
结构体变量的使用
赋值,实际上是对成员变量进行赋值
//结构体变量名.成员变量名
struct Student p;//p是结构体变量
p.age = 10;
printf("p.age: %d\n",p.age);//访问的时候只能输出成员变量
取值,实际上是把成员变量的值取出来输出
struct Student q;
q = p;//结构体变量之间是可以相互赋值 q.day == p.day!!!!
//注意:不能printf("?",p);不能整体进行输出
printf("p.age: %d\n",p.age);
结构体指针变量的访问
定义
//定义格式:struct 结构体名* 指针变量名;
struct Student* s;//s是一个指针变量名,指向的类型应该是struct Student
//1
struct Student p;//p是结构体变量
s = &p;
//2
s = (struct Student* )malloc(sizeof(struct Student));
//3
struct Student* q;
q = p;//p和q指向同一个空间
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PGr0HJFy-1609289927734)(结构体笔记1.assets/image-20201229105634106.png)]
赋值(通过结构体指针变量对成员变量赋值)
//使用s,对s指向的空间中(p)的成员变量(name,age)进行赋值
//定义格式: 结构体指针变量->成员变量
s->age = 10;
s->sex = 'f';
strcpy(s->name,"lisi");
取值(通过结构体指针变量把指向的空间的成员变量值取出来)
printf("%d",s->age);
printf("%s",s->name);
⚠️结构体变量 不能整体输入和输出,只能一个一个输入或者输出其成员变量
定义结构体数组
struct Student stu[5];//定义了5个结构体变量
//访问成员变量
stu[0] stu[0].age
stu[1] stu[1].age
。。。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZqE4wqxo-1609289927736)(结构体笔记1.assets/image-20201229144752352.png)]
结构体变量的初始化
struct Student{
char name[20];//
int age;
};
-
按照定义的顺序进行初始化
struct Student s = {"zhangsan",10};
-
不按照顺序进行初始化
struct Student s = { .age = 10, .name = "zhangsan" };
-
结构体数组进行初始化
- 按顺序进行初始化
struct Student stu[5] = { { "zzhangsan",10 },//stu[0] { .age = 10, .name = "lisi" }//stu[1]的值 }
b.不按照顺序初始化(不是所有的编译器支持)
struct Student stu[5] = { [1] = { "zzhangsan",10 },//stu[1] [2] = { .age = 10, .name = "lisi" }//stu[2]的值 }
结构体中字节对齐
-
结构体内部的成员变量需要在指定的起始地址上进行存储,跟系统的位数相关(32 64 )
-
结构体存储的时候会指定起始的地址,即结构最终的字节数按照最大宽度进行字节对齐
最大宽度:成员变量中 字节对齐的值 最大的
32位:
char 1字节对齐,要求存储的地址1的整数倍
short 2字节对齐,要求存储的地址2的整数倍
int 、long 、float 、指针变量 4字节对齐,要求存储的地址4的整数倍
double Windows 8字节对齐,Linux上是4字节对齐
struct MixData{
char d1;// 0 -- 1
short d2;//2 ---> 2
}
sizeof(struct MixData) <=====> 4
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y3xKXiHm-1609289927738)(结构体笔记1.assets/image-20201229154850450.png)]
struct MixData{
char d1;// 0
int d2;//4 5 6 7
char d3//8
};//9 个,最大宽度:4
//的大小是最大宽度的整数倍 ---> 12
sizeof(struct MixData)<==============> 12
64位系统:
char 1字节对齐,要求存储的地址1的整数倍
short 2字节对齐,要求存储的地址2的整数倍
int 、float 、指针变量 4字节对齐,要求存储的地址4的整数倍
long doouble 8字节对齐,要求存储地址8的整数倍
struct MixData{
char a1;// 0
char a2;//1
int a3;//4 5 6 7
};
sizeof(struct MixData) <=====> 8
struct MixData{
char a1;//0
int a3;//4 5 6 7
char a2;//8
};//9 整体对齐: 最大的宽度 4 ===
sizeof(struct MixData) <=====> 12
struct MixData{
int a3;//0 1 2 3
char a1; //4
char a2;//5
};
sizeof(struct MixData) <=====> 8
struct MixData{
char a1;//0
double a3;//8 9 10 11 12.. 15
char a2;//16
};//17 ---> 最大宽度(8)
sizeof(struct MixData) <=====> 24
练习
-
定义struct Student 结构体变量,对齐进行赋值和输出
-
输入5个结构体变量,按照年龄大小进行排序输出+
struct Student{ char name[20];// int age; }; //1.输入 【结构体数组】 //2.排序 //3.输出【使用指针变量的形式】 p = &stu[0];//通过p输出其成员变量
-
结构体数组输入与输出\
//1.输入 struct Student s[5];//s[0] s[1] int i = 0; for(i = 0; i < 5; i++){ scanf("%s %d",s[i].name,&s[i].age); } for(i = 0; i < 5; i++){ printf("%s %d\n",s[i].name,s[i].age); }
b.结构体数组输入与输出
//2. 输入与输出 struct Student* stu;//stu中存储的是随机值,指向的空间随机 for(int i = 0; i < 5; i++){ stu = &s[i];//&(s[0]) &s[1] (s + i) scanf("%s %d",stu->name,&stu->age); } //2.排序 //3.输出 for(int i = 0; i < 5; i++){ stu = (s + i); printf("%s %d\n",stu->name,stu->age); //printf("%s %d",(*stu).name,(*stu).age); }
-
-
结构体的大小
struct FinalPad{ float x;//4 0 1 2 3 char n[1];//1 4 };//5 ---> 整个结构字节对齐: 8 sizeof(struct FinalPad) ===