结构体的创建
举个栗子:创建结构体叫学生,包含(学号,名字,性别,成绩)
struct student { int id; //学号 char name[5]; //名字 char sex[4]; //性别 double scorce;//成绩 };
结构体创建👆解释
结构体变量的定义和初始化
变量的定义
struct student { int id; //学号 char name[5]; //名字 char sex[4]; //性别 double scorce;//成绩 }p1; //定义一:定义变量p1 struct student p2;//定义二:定义结构体变量p2
初始化
struct student { int id; //学号 char name[5]; //名字 char sex[4]; //性别 double scorce;//成绩 }p1; //定义一:定义变量p1 struct student p2;//定义二:定义结构体变量p2 struct student p3 = { 1,"bai","nan",99.9 };//初始化一 struct student p4 = { .sex = "nan",.name = "ran",.id = 2,.scorce = 88.8 };//二:指定顺序初始化
结构体嵌套结构体
//出生日期数据 struct Data { int year; int month; int day; }; struct student { int id; //学号 char name[5]; //名字 char sex[4]; //性别 double scorce;//成绩 struct Data birthday;//结构体嵌套结构体 }a1 = { 1,"bai","nan",99.9,{2003,8,27} }; //结构体嵌套初始化一 struct student a2 = { .birthday = {2006,8,23},.id = 2,.name = "ran",.scorce = 88.8,.sex = "nan" };//结构体嵌套初始化二
结构体访问成员
方式一:使用 . 访问
struct student { int id; //学号 char name[5]; //名字 char sex[4]; //性别 double scorce;//成绩 }p1; //定义一:定义变量p1 struct student p2;//定义二:定义结构体变量p2 struct student p3 = { 1,"bai","nan",99.9 };//初始化一 struct student p4 = { .sex = "nan",.name = "ran",.id = 2,.scorce = 88.8 };//二:指定顺序初始化 int main() { printf("id = %d\nname = %s\nsex = %s\nscorce = %.2lf\n", p3.id, p3.name, p3.sex, p3.scorce);//用 . 访问成员 return 0; }
方式二:用指针访问
struct student { int id; //学号 char name[5]; //名字 char sex[4]; //性别 double scorce;//成绩 }p1; //定义一:定义变量p1 struct student p2;//定义二:定义结构体变量p2 struct student p3 = { 1,"bai","nan",99.9 };//初始化一 struct student p4 = { .sex = "nan",.name = "ran",.id = 2,.scorce = 88.8 };//二:指定顺序初始化 int main() { //访问成员方式一 printf("id = %d\nname = %s\nsex = %s\nscorce = %.2lf\n", p3.id, p3.name, p3.sex, p3.scorce);//用 . 访问成员 //访问成员方式二 struct student* t = &p4; printf("id = %d\nname = %s\nsex = %s\nscorce = %.2lf\n", t->id, t->name, t->sex, t->scorce);//用指针->访问成员 return 0; }
(*p). 成员名( . 的优先级高于 * ,(*p)两边括号不能少)
结构体与函数
struct student { int id; //学号 char name[5]; //名字 char sex[4]; //性别 double scorce;//成绩 }; void print(struct student* p)//形参:结构体指针变量 { printf("id = %d\nname = %s\n", p->id, p->name);//打印学号和名字 } int main() { struct student p = { 1,"bai","nan",99.9 };//定义p和初始化 print(&p);//传p的地址 return 0; }
控制台输出:
结构体内存对齐
对齐规则
1.结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的⼀个对齐数与该成员变量大小的较小值。
VS默认的对齐数为8
Linux中gcc没有默认对⻬数,对齐数就是成员自身的大小
3. 结构体总大小为最⼤对齐数(结构体中每个成员变量都有⼀个对齐数,所有对齐数中最⼤的)的整数倍。
4. 嵌套结构体,嵌套的结构体成员对齐到自己的成员中最⼤对齐数的整数倍处,结构体的整体大小就是所有最⼤对齐数(含嵌套结构体中成员的对齐数)的整数倍。
先看下面👇两段代码
示例
①段代码
struct s1 { char c1; int i; char c2; }; int main() { printf("%zd\n", sizeof(struct s1)); return 0; }
②段代码
struct s1 { char c1; char c2; int i; }; int main() { printf("%zd\n", sizeof(struct s1)); return 0; }
代码结果解释:
③段代码:嵌套结构体
struct S1 { double d; char c; int i; }; struct S2 { char c1; struct S1 s1; double d; }; int main() { printf("%zd\n", sizeof(struct S2)); return 0; }
代码结果解释
小结:结构体的内存对齐是拿空间来换取时间的做法。
修改默认对齐数
#pragma (一个预处理指令):可以改变编译器的默认对齐数
#pragma pack(1) //设置默认对齐数为1 struct s1 { char c1; char c2; int i; }; //#pragma pack() //取消默认对齐数,还原为默认 int main() { printf("%zd\n", sizeof(struct s1)); return 0; }
控制台输出:6