目录
1.结构体的组成
2.结构体的定义和声明
3.初始化和成员访问
4.结构体嵌套
5.结构体内存大小计算
序言
在前面我们学习了各种类型的变量,如int ,float,double等等,但是他们都有一个共同的特点:就是只存储一个数据,而且每个变量内存都是独立的;但是现实生活中的许多事物的各种属性都是相连的,共同组成了一个整体,例如:统计一个班上学生的姓名,身高,体重等特性,毫无疑问这都是共同属于一个人的,是一个整体;对于此类问题,我们使用结构体来进行解决。
组成
这里我们先来看一个结构体:
struct A{ int b; float c; double d;};
1.struct:struct是结构体的标志,使用结构体必须在开头是用struct;
2.结构体名字:A(标识符)是结构体的名字,用于对结构体进行标记,如果在程序中就只有一个结构体,那么我们可以不用写名字A,因为我们知道就是那个唯一的结构体。但是如果有两个及以上的结构体,那么用于区分就需要写上名字啦。
3.成员内容:结构体内部的数据项用花括号进行包含;内容可以是各种的变量类型,用于表示结构体目标的各个特点。
4.分号:在最后必须有分号。
定义和声明
#define _CRT_SECURE_NO_WARNINGS 1#includestruct person{char name[99];int year;};struct book{ char name[99]; int year_from;}c;//在声明结构体的时候,定义变量.typedef struct book{ char name[99]; int year_from;}B;int main(){person a;struct person b; B d;//B相当于struct book;}
声明
1.结构体的声明:声明通常是在main函数的上面,类似于自定义函数。
2.声明的时候最后分号容易露掉。
定义
1.struct+名字:如上图,我声明了一个person的结构体,在main函数中可以用struct person直接进行定义结构体变量。
2.名字:也可以直接用结构体的名字进行定义结构体变量,如persona。
3.在声明的同时定义:在声明的最后分号前面加上一个变量名,就定义好了,在main函数中就可以直接使用了。
4.用typedef给结构体别名:上图用B代表了struct book,使用更方便,但是需要注意的是,别名是在分号的前面,不要与前面的情况弄混了。
初始化和成员访问
初始化
初始化有两种方式,1.在定义的时候,进行初始化。2.通过对结构体成员的访问进行初始化或者修改值。
#define _CRT_SECURE_NO_WARNINGS 1#include#includestruct person{char name[99];int year;};int main(){person student = { "派蒙",18 };//初始化的同时进行初始化。strcmp(student.name, "空/莹");//进行字符串的拷贝student.year = 20;//修改年龄}
成员访问
普通变量
普通变量进行对结构体成员的访问使用’.'(点)。
结构体指针
int main(){person student = { "派蒙",18 };person* ps = &student;printf("%d", ps->year);puts(ps->name);}
结构体指针是通过->来访问结构体变量的。
结构体嵌套
#define _CRT_SECURE_NO_WARNINGS 1#includestruct book{ char name[99]; int year_from;};struct person{char name[99];int year;struct book B;};
在结构体里面在定义一个结构体就实现了结构体的嵌套,在其中对book成员的访问就需要访问两次了.在这里不再多说。
结构体内存大小计算
序言
结构体的内存大小计算涉及到对结构体内部各成员的对齐和填充规则的理解。在C语言中,结构体的内存大小由其成员的大小和对齐方式决定。以下是一些计算结构体内存大小的基本规则:
1.对齐规则: 结构体的每个成员都有一个对齐要求,要求成员的地址是其大小的倍数。对齐规则可以由编译器根据目标平台和编译选项而定。
2.成员对齐: 结构体的每个成员按照其自身的大小对齐,但不能超过结构体的对齐要求。
3.填充: 编译器可能会在结构体成员之间插入填充字节,以满足对齐要求。
正文
计算结构体的内存大小的一般步骤如下:
1.对结构体的每个成员按照其大小进行对齐。
2.计算每个成员的偏移量。
内存对齐
第一步:找出每个成员变量的大小将其与编译器的默认对齐数相比较,取其较小值为该成员变量的对齐数。
在成员变量自身与默认对齐数之间取较小的数作为该变量的字节对齐数;
请注意,实际的对齐规则可能因编译器、编译选项和目标平台而异。可以使用 sizeof 运算符来获取结构体的大小。
注意:vs编译器的默认对齐数是8;
第二步:根据每个成员对应的对齐数画出它们在内存中的相对位置。
注意:内存的偏移起点是0;偏移位置必须是在变量的对齐数的倍数上才能实现字节对齐。
以下是一个例子:
// 定义一个结构体struct Example {char a;// 1字节int b; // 4字节double c; // 8字节};int main() {struct Example example;// 计算结构体大小printf("Size of struct Example: %lu bytes\n", sizeof(example));return 0;}
在这个例子中,char 类型的成员 a 需要1字节,int 类型的成员 b 需要4字节,double 类型的成员 c 需要8字节。由于对齐规则,可能在 a 和 b 之间插入填充字节。计算总大小时,需要考虑这些因素,
所以该结构体大小是1+3(填充)+4+8=16;
特点:结构体的大小一定是默认对齐数的整数倍;