目录
1.什么是结构体?
2.为什么要有结构体?
3.结构体的声明,定义,初始化
1.简单的结构体创建变量
2.加 typedef 作用是:类型重命名
3.结构体中的结构体
4.结构体的传址,传值
5.结构体的传址,传值 哪种好?
创作不易,如果本篇博客对您有一定的帮助,大家记得留言+点赞哦。
就是用户自己定义的一种类型,你可以自己去定义这个类型的一系列属性。比较常用的自定义类型有:结构体, 联合体,枚举。
由于在实际问题中,一组数据往往有很多种不同的数据类型。例如,登记学生的信息,可能需要用到 char型的姓名,int型或 char型的学号,int型的年龄,char型的性别,float型的成绩。又例如,对于记录一本书,需要 char型的书名,char型的作者名,float型的价格。在这些情况下,使用简单的基本数据类型甚至是数组都是很困难的。而有了结构体,我们可以借助它可以有效的解决这个问题。
结构体本质上还是一种数据类型,但它可以包括若干个“成员”,每个成员的类型可以相同也可以不同,也可以是基本数据类型或者又是一个构造类型。
结构体的优点:结构体不仅可以记录不同类型的数据,而且使得数据结构是“高内聚,低耦合”的,更利于程序的阅读理解和移植,而且结构体的存储方式可以提高CPU对内存的访问速度。
struct stu { //结构体声明 注:struct stu 是【结构体类型名】
char name[20]; // s2,s3 是【变量名】
int age; // name[],age,sex[] 是【结构体成员名】
char sex[5];
}s2,s3; //此处可创建变量 --为全局变量 ;冒号不要忘记
struct stu s4;// 此处也可创建变量 --为全局变量
int main() {
struct stu s1; //--局部变量
return 0;
}
struct stu 是【结构体类型名】
s2,s3, s4是【变量名】且是全局变量 s1是局部变量
name[],age,sex[] 是【结构体成员名】
typedef struct stu { //这里的 S(大括号后跟的) 是 【结构体变量】
char name[20];
int age;
char sex[5];
}S; // 给【struct stu】整体起了个名【S】
int main() {
S s1; //即 S 等价于 struct stu
return 0;
}
//初始化及打印
struct A {
char name[20];
int age;
char sex[5];
};
struct B {
char dept[20];
struct A a; //在结构体中定义结构体变量
char sno[10];
};
int main() {
struct A aa = {"赵亦",20,"男"}; //初始化
struct B b = { "计算机",{"赵亦",20,"男"},"001"}; //初始化
printf("%s %d %s\n",aa.name,aa.age,aa.sex);
printf("%s %s %d %s %s",b.dept,b.a.name,b.a.age,b.a.sex,b.sno);
return 0;
}
struct st {
char name[20];
int age;
char sex[5];
};
void set_st(struct st s) { //传值 不能改变原有的
s.age = 20;
strcpy(s.name,"赵亦");
strcpy(s.sex,"男");
//s.name = "赵亦"; //这种形式是错误的name,sex 为数组名,指针 不能为左值
//s.sex = "男";
}
void set_stt(struct st *ss) { //传址 可改变原有的
ss->age = 20;
strcpy(ss->name, "赵亦");
strcpy(ss->sex,"男");
//printf("%s %d %s", ss->name, ss->age, ss->sex);
//或者下面形式 【即ss->age 等价于 (*ss).age】
//(*ss).age = 20;
//strcpy((*ss).name, "赵亦");
//strcpy((*ss).sex, "男");
//printf("%s %d %s", (*ss).name,(*ss).age,(*ss).sex);
}
void print_st(struct st s) {
printf("%s %d %s\n",s.name,s.age,s.sex );
}
int main() {
struct st s = { 0 }; //初始化结构体
struct st ss = { 0 };
set_st(s); //结构体传值
print_st(s);
set_stt(&ss); //结构体传址
print_st(ss);
return 0;
}
在一般情况下,我们都是会去传址的,不仅因为它快,高效。而是如果传值,函数在传参的时候是需要压栈的,若此时结构体过大,参数压栈时系统的开销也就较大,会导致性能的下降。
并且传址不管你结构体有多大,我传递的地址永远是4/8个字节,开销远比传值小得多。故首选传址。
那有时候我们传值的目的是只使用访问而不改变原有的数据。如果都传址,万一不小心改变数据该怎么办。这里根据自己的使用场景,可以加const,从而防止数据改变。
struct st {
char name[20];
int age;
char sex[5];
};
void set_stt(const struct st * ss) { //加const传址 原数据不能被改变
//ss->age = 20; 会报错
//(*ss).age = 20; 会报错
printf("%s %d %s", ss->name, ss->age, ss->sex);
}
int main() {
struct st ss = { 0 };
set_stt(&ss);
return 0;
}