目录
一、结构体的基础知识
结构体 :
一组 不同类型元素 的集合,这些值称为 成员变量 ,每个成员可以是不同 类型 的变量(char , int , float , double.....);
对 复杂对象 的描述 就会使用到: 结构体
- 人: 名字+电话+性别+身高
- 书:书名+作者+定价+书号
另解:结构体差不多就是类 创建结构体变量相当于实例化
但 结构体内 不能定义函数 所以跟类还是有区别的
结构体和数组比较
数组:一组相同类型元素的集合
二、结构体的声明 与 各结构分析
(1)结构体各成分 分析
- struct : 结构体关键字
- Stu : 结构体标签___自定义的,具有意义
- p1 : 结构体变量
- s.name:中间这个点为 结构体 操作符
- {"zhansan","17", 99.9f} :这些 量时一一存放在 结构体对应的数组中的
- char namel20]; int age; double score; : 结构体成员变量
- struct st s 中的 struct st 意义:直观理解就是 类似于在 int a 中 int 是 变量a 的类型名 而 struct Stu s 中 struct stu 是 变量s 的类型名
温馨提示:千万别忘了 创建结构体 要加上 " ; "
struct Stu
{
char name[20];
int age;
float score;
};
int main()
{
struct st s = {"zhansan","17", 99.9f};
printf("名字:%s ,年龄:%s ,分数:%f", s.name, s.age, s.score);
return 0;
}
(2)结构体变量的声明
结构体变量的声明:先创建好 结构体 struct Stu 后 使用
结构体的声明位置: 影响使用结构体范围,上面代码中的声明是放在 函数外部,使用范围 会比放在 函数内部 内部声明 更大,类似全局变量和局部变量的关系
三、结构体的另一种正确写法 (尽量少用)
- p1和p2 是使用struct Stu 结构类型 创建的 2个 全局 结构体变量
- 建议少用:在 使用时 需要创建 结构体变量 时,再创建 , 不必要提前 在此创建,就像 上一张代码图中 结构体变量 p1 在main函数的使用
struct Stu
{
char name[20];
int age;
double score;
}p1, p2;
四、关于 结构体初始化
这里可以直接初始化
struct Stu
{
char name[20];
int age;
double score;
}p1= { "zhansan", "18", 99.9 }, p2 { "lisi", "19", 97 };
不按默认顺序来初始化: 通过 点 . 操作符 对变量进行引用,可以改变顺序
初始化默认按顺序一一对齐;也可以通过 .name = .. 这样不按默认顺序来
p1= { .age="18", .name="zhansan", .score=99.9 }, p2 { "lisi", "19", 97 }
五、结构成员的类型
结构的成员可以是标量、数组、指针,甚至是其他结构体
(如下图在struct st中 将 struct Peo p 作为结构体成员)
(一层层剖析,一个属性之下可能有更细致的 属性划分)相当于一个 学生student 的内层还可以细化分析 这个学生作为 人person 的属性
struct Peo
{
char name[20];
char tele[12];
char sex[5];
int high;
};
struct st
{
struct Peo p;
int num;
float f;
};
六、"嵌套结构体” 重要栗子: 重要规律
规律:
1、结构体1 中有 以结构体2 作为成员变量: 初始化结构体1 时 在结构体2 位置用大括号 { }将结构体2初始化
例如:struct st s = {{"zhansan","15812305977","nan"}, "2300502113". 99.9f};
2、"连环"结构体成员访问:引用结构体1 中的成员结构体2 的成员 模式--> (结构体变量s . 结构体变量p1 . p1的成员)
例如:s.p1.name, s.p1.tele, s.p1.sex
struct Peo//张三本人people的属性
{
char name[20];
char tele[12];
char sex[5];//女 男 保密
};
struct st//张三的学生属性
{
struct Peo p1;//在张三的学生student属性中,细化张三本人people的属性
char xuenum[11];//学号
float score;//分数
};
int main()
{
struct st s = {{"zhansan","15812305977","nan"}, "2300502113". 99.9f};
printf("名字:%s ,电话:%s ,性别:%s ,学号:%s ,分数:%f",
s.p1.name, s.p1.tele, s.p1.sex, s.xuenum, s.score);
return 0;
}
七、结构体传参: 以 创建打印功能的函数 为栗子
温馨提示:代码较长 请自行拖动 代码块 下方的 拖条 查看全部代码
-
(1)普通传参: 结构体对象.成员变量(传参耗时耗空间)
void print(struct st s) { printf("名字:%s ,电话:%s ,性别:%s ,学号:%s ,分数:%f", s.p1.name, s.p1.tele, s.p1.sex, s.xuenum, s.score); }
-
(2)指针法的两种写法
模式:
1、 结构体指针->成员变量;
2、结构体指针解引用 . 成员变量
注意 : *ps = s (两者完全等价)
-
void print(struct st* ps) { printf("名字:%s ,电话:%s ,性别:%s ,学号:%s ,分数:%f", ps->p1.name, ps->p1.tele, ps->p1.sex,ps->xuenum, ps->score); } void print(struct st* ps) { printf("名字:%s ,电话:%s ,性别:%s ,学号:%s ,分数:%f", (*ps).p1.name, (*ps).p1.tele, (*ps).p1.sex, (*ps).xuenum, (*ps).score); }
-
结构体传参优先使用 指针传地址法:
相比于直接传参 更加省时省空间,效率更高
原因:如果传递一个结构体对象的时候,结构体过大,
参数压栈的的系统开销比较大,会导致性能的下降
-
(3)关于浮点数注意事项
打印出来的 数值 会不精确: 如 下图 分数 :99.900002
因为在内存中 不可以 精确的保存 浮点数
(关于浮点数在内存中如何存储在这里暂时不做分析)