目录
一.结构体类型
结构体类型是一种自定义类型
C语言中自定义类型有:结构体,枚举,联合体
结构体中有成员变量,每个成员变量都有不同的类型
结构是许多变量的集合
一个学生有许多元素构成所以用结构体
struct是关键字,student是类型名,也是结构体标签
struct student
{
char name[20];
int age;
};
二.结构体变量的创建和初始化
struct student
{
char name[20];
int age;
char id[20];//学号
}m;//变量s
int main()
{
//结构体变量的创建和初始化
//按照顺序初始化
struct student s = { "zhangsan",20,"20231212" };
//不按顺序初始化
struct student a = { .age = 20,.id = "20329393",.name = "wanger" };
return 0;
}
1. typedef可以是类型名简化
//typedef 将struct student 这个类型重命名为p
//就可以用p 去创建变量
typedef struct student
{
char name[20];
int age;
char id[20];//学号
}p;//变量s
typedef struct student s;
//将struct student 这个类型重命名为s
//就可以用s 去创建变量
int main()
{
//结构体变量的创建和初始化
//按照顺序初始化
p i = { "zhangsan",20,"20231212" };
//
s e = { "lisi",19,"293942"};
//不按顺序初始化
p i = { .age = 20,.id = "20329393",.name = "wanger" };
return 0;
}
2.匿名的结构体类型
匿名的结构体类型,如果没对结构体类型重命名的话,基本上只能使用一次
//省略了结构体标签
//匿名的结构体类型
struct
{
int year;
char arr[20];
}x;//变量
3.结构体的自引用
自引用:在结构体中包含自己本身的结构体类型的变量
struct ss
{
int i;
struct ss p;
}
这样写是错的,结构体的大小里面再包含一个结构体+一个整型的大小
正确的写法:
struct ss
{
int i;//4大小
struct ss * p;// 4/8
}
三.结构体的内存对齐
1.对齐规则
- 结构体的第一个成员对齐到偏移量为0的地址处
- 其他成员对齐到对齐数整数倍的地址
- 对齐数 = 编译器默认的值(字节大小)和成员变量(字节大小)的较小值
- 结构体的总大小是最大对齐数(就是该结构体中成员变量之间的最大值)
- 如果嵌套了结构体,结构体的总大小是成员变量中最大值的整数倍(含嵌套的结构体)
- 偏移量/字节大小 = 整数倍
- VS中对齐数为8
1.1 例一:
struct S1
{
char c1;//1 8 1
int i;// 4 8 4
char c2;// 1 8 1
};
printf("%d\n", sizeof(struct S1));
大小为:12
1.2例二:结构体嵌套
struct s1
{
double d;//8 8 8
char c;// 8 1 1
int i;// 8 4 4
};
struct s
{
char c1;//8 1 1
struct s1 a;
double d;//8 8 8
};
大小为:32
四.结构体传参
要传结构体的地址,地址压栈比较小 而传结构体过去,结构体压栈的开销比较大,会导致性能的下降
五.结构体实现位段
5.1位段的声明
1.位段的成员名的类型必须是int,unsigned int,signed int 在C99位段的成员也可以选择其他类型
2.位段的成员后有冒号和一个数字(这个数字表示bit位大小)//_结构体成员名也可以使用
struct S
{
int _a : 2;// 2 bit
int _b : 5; // 5 bit
};
位:指的是二进制位
位段是专门用来节省内存的
5.2位段的内存分配
struct A
{
char_a:3;
char _b:4;
char _c:5;
char _d:4;
};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
int main()
{
sizeof(struct A);
return 0;
}
5.3位段使用要注意的地方
1.内存中每个字节分配地址,一个字节内的bit位是没有地址的。
2.位段的成员是不能是用&操作符的,所以不可以直接给位段成员scanf(输入值),只能先输入一个值放入一个变量中,然后这个变量再赋值给位段的成员。