目录
一.基础详解
定义:它是不同数据类型的集合
- 结构体关键字是struct
- Student是自定义的结构体名/结构体标签名/结构体名称(首字母最好大写,可以与变量区分)
- {}里面放的是成员列表,或者叫结构体成员,结构体成员不能初始化,其中的id,age,name叫成员名
- struct+结构体名=数据类型/结构类型/结构体类型, 这个数据类型也就和int,double等那些数据类型是一样的
- 大括号内是成员列表,这个成员列表里面不仅可以有基本成员列表,还可以有复合数据类型,甚至还可以有结构体
二.结构体变量初始化(一共5种)
1. 默认顺序初始化
2. 自定义初始化顺序
3. 定义时直接赋值
4.
5. 结构体数组初始化
三. typedef 类型重命名
其中type是类型,def是定义
重命名的优点: 减少麻烦,更加方便,简单
eg.
第1种写法:
第2种写法:
四.嵌套
eg.在学生结构体里面去嵌套一个生日结构体
五.匿名结构体
优点:嵌套在结构体中的结构体为匿名结构时,可以直接访问其成员
一般来说,结构体中的局部变量都是通过结构体名称来命名,这样会更加方便
但若是匿名结构体呢?
在这个例子中,我们定义了一个匿名结构体变量 `employee`,它包含三个成员:`id`、`name` 和 `salary`。
我们没有为这个结构体指定一个类型名称,因此它不能被用来定义其他同类型的变量。
六.结构体作为函数参数
#include<stdio.h>
typedef struct Birthday
{
int year;
int month;
int day;
}Birthday;
typedef struct Student
{
int id;
char name[10];
int age;
float score;
Birthday birthday;
}Student;
int main()
{
Student stu1 = { .id = 1001,.name = "xiaohong",.age = 28,.score = 99.0,
.birthday = {.year = 2005,.month = 3,.day = 12} };
Student stu2 = { .id = 1002,.name = "xiaoming",.age = 23,.score = 87.6,
.birthday = {.year = 2006,.month = 7,.day = 23} };
printf("%d\n%s\n%d\n%.2f\n%d\n%d\n%d\n", stu1.id, stu1.name, stu1.age,stu1.score,
stu1.birthday.year, stu1.birthday.month, stu1.birthday.day);
printf("%d\n%s\n%d\n%.2f\n%d\n%d\n%d\n", stu2.id, stu2.name, stu2.age, stu2.score,
stu2.birthday.year, stu2.birthday.month, stu2.birthday.day);
//像上面这样写2个printf打印虽然没有错,但是不规范,所以,就得通过让结构体作为函数参数
//这个方法(具体参照下面的代码和这个代码的区别)
return 0;
}
更规范的写法:
#include<stdio.h>
typedef struct Birthday
{
int year;
int month;
int day;
}Birthday;
typedef struct Student
{
int id;
char name[10];
int age;
float score;
Birthday birthday;
}Student;
void printStudentinfo(Student stu)
{
printf("%d\n%s\n%d\n%.2f\n%d\n%d\n%d\n", stu.id, stu.name, stu.age, stu.score,
stu.birthday.year, stu.birthday.month, stu.birthday.day);
}
int main()
{
Student stu1 = { .id = 1001,.name = "xiaohong",.age = 28,.score = 99.0,
.birthday = {.year = 2005,.month = 3,.day = 12} };
Student stu2 = { .id = 1002,.name = "xiaoming",.age = 23,.score = 87.6,
.birthday = {.year = 2006,.month = 7,.day = 23} };
printStudentinfo(stu1);
printStudentinfo(stu2);
return 0;
}
七.使用结构体指针
- 像上面的printStudentinfo这种是值传递,它需要拷贝一份然后值传递,然后才能打印,这样的话,电脑的任务比较繁重,运行速率也会降低
- 所以用指针,只用传递主函数里面stu1和stu2的地址,而不是拷贝,这样会加快代码的效率
#include<stdio.h>
typedef struct Birthday
{
int year;
int month;
int day;
}Birthday;
typedef struct Student
{
int id;
char name[10];
int age;
float score;
Birthday birthday;
}Student;
void printStudentinfo(Student *pStu)
{
printf("%d\n%s\n%d\n%.2f\n%d\n%d\n%d\n", pStu->id, pStu->name, pStu->age, pStu->score,
pStu->birthday.year, pStu->birthday.month, pStu->birthday.day);
//注意这里的year,month,day的这种嵌套,你就不用用->,用之前的.就行
}
int main()
{
Student stu1 = { .id = 1001,.name = "xiaohong",.age = 28,.score = 99.0,
.birthday = {.year = 2005,.month = 3,.day = 12} };
Student stu2 = { .id = 1002,.name = "xiaoming",.age = 23,.score = 87.6,
.birthday = {.year = 2006,.month = 7,.day = 23} };
Student* pStu = &stu1;//即pStu这个指针指向stu1,即stu1的地址赋值给了pStu
printStudentinfo(pStu);
pStu = &stu2;//这一行因为pStu之前已经指向过了stu1,并且已经完成了打印,所以这一行就重新让它指向stu2
printStudentinfo(pStu);
return 0;
}
八.结构体内存计算
结构体内存计算用内存对齐
- 对齐数是类型的大小
- VS当中的默认对齐数是8
- 对齐数和默认对齐数比较取较小值,这个较小值便在偏移量中找位置占据就行哪个位置?找这个较小值整数倍的位置占据,值是多少,偏移量即是多少
- 当对齐数和默认对齐数比较之后得出的结果再放在一起比较,其中最大的,就是最大对齐数
- 最后找出最大对齐数,也是在其整数倍处开始占据
- 那什么时候会产生最大成员数,就是当是数组的时候,比如char c[5],对齐数是1,VS默认对齐数是8,而最大成员数是5
- 当最大成员数不是最大对齐数的整数倍时,则要对齐到最大对齐数的整数倍
举例说明:
例1:
解析:
首先是char c1; 因为char的大小是1,VS默认对齐数是8,1和8作比较,选最小数为1
其次是int i; 是4和8作比较,选4,偏移量中选4的倍数处占据
最后是char c2; 是1和8作比较,选1,偏移量中选1的倍数处占据
最后选出最大对齐数是4(就是通过上面的1,4,1中选),再在偏移量中选4的倍数处占据
偏移量表格:
0 | char c1 |
1 | |
2 | |
3 | |
4 | int i |
5 | int i |
6 | int i |
7 | int i |
8 | char c2 |
9 | |
10 | |
11 | |
12 | 最大对齐数是4 |
13 |
所以最终结果是12
例2:
解析:
0 | d |
1 | d |
2 | d |
3 | d |
4 | d |
5 | d |
6 | d |
7 | d |
8 | c |
9 | |
10 | |
11 | |
12 | i |
13 | i |
14 | i |
15 | i |
16 | 最大对齐数是8 |
17 | |
18 |
例3:
嵌套结构体如何算?
解析:
如果是嵌套结构体,那就对齐到自己成员里最大对齐数的整数倍处就好
S3的结构体里最大对齐数是8,所以对齐到8的倍数处,占16个位置
S4里最大对齐数是16,因为是(1,16,8比较)
0 | char c1 |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | struct S3 s |
9 | struct S3 s |
10 | struct S3 s |
11 | struct S3 s |
12 | struct S3 s |
13 | struct S3 s |
14 | struct S3 s |
15 | struct S3 s |
16 | struct S3 s |
17 | struct S3 s |
18 | struct S3 s |
19 | struct S3 s |
20 | struct S3 s |
21 | struct S3 s |
22 | struct S3 s |
23 | struct S3 s |
24 | d |
25 | d |
26 | d |
27 | d |
28 | d |
29 | d |
30 | d |
31 | d |
32 | 最大对齐数16 |
33 |
所以答案是32
九.结构体自引用
十.结构体实现位段
写作不易,若有疑问,请各位大佬指教~感谢!