前言
大家有没有想过为什么会出现结构体这个东西呢,原因是我们生活中有很多复杂的对象,比如说一个人,一本书,不能用一个简单数字就描述清楚。结构体由一组不同的类型的成员组合而成,通常用来表示类型不同但是又相关的若干数据,结构体类型不是由系统定义好的,而是需要程序设计者自己定义的。
结构体与数组不同 数组是一组相同类型元素的集合
而结构体是由一组不同类型元素组成的
结构体的声明
自定义数据类型strcut后面可以加合适的标签名
struct tag //结构体声明,strcut后可以自定义合适的标签名
{
//....
//成员列表
};
结构体类型的声明
结构体成员的类型可以是变量、数组、指针、甚至是其他结构体
例如一个学生:
struct Stu
{
char name[20];//名字
short age;//年龄
char sex[5];//性别
int id;//学号
};//分号不能丢
结构体变量的定义和初始化
有了结构体的类型,那如何定义变量呢?
struct Stu 相当于int, float…
s1 相当于我们的变量名
struct Stu
{
char name[20];//名字
short age;//年龄
char sex[5];//性别
int id;//学号
};
struct Stu s2;//全局变量
int main()
{
struct Stu s1;//结构体变量的定义
return 0;
}
那么如何初始化呢
struct Stu
{
char name[20];//名字
short age;//年龄
char sex[5];//性别
int id;//学号
};
int main()
{
struct Stu s1 = {"William", 21, "male", 386910};
return 0;
}
结构体成员的访问
初始化完,我们如何访问呢,这里我们需要(.)操作符进行访问
(.)后面加成员名
struct Stu
{
char name[20];//名字
short age;//年龄
char sex[5];//性别
int id;//学号
};
int main()
{
struct Stu s1 = {"William", 21, "male", 386910};
printf("name=%s, age=%hd, sex=%s, id=%d\n", s1.name, s1.age, s1.sex, s1.id);
return 0;
}
运行结果:
上面说到结构体中不仅由整形变量,浮点型,字符,也可以有结构体
我们又创建了一个struct P,成员是int类型和char类型
接着我们把struct P放到struct Stu里,结构体嵌套结构体
struct P
{
int n;
char ch;
};
struct Stu
{
char name[20];
short age;
char sex[5];
int id;
struct P p;
};
int main()
{
struct Stu s1 = { "William", 21, "male", 386910, {11, 'C'}};//结构体嵌套结构体也需要使用大括号
printf("%d, %c\n", s1.p.n, s1.p.ch);//只打印struct P里面的成员
return 0;//需要先s1.找到Stu里的成员,再.p找到P里面的成员,再.找到对应的成员
}
运行结果:
***********可想而知,这就不放图了
结构体传参
我们写一个Print打印函数把s1传过去,我们用s2接收,然后打印结构体成员
传值调用:
struct Stu
{
char name[20];
short age;
char sex[5];
int id;
};
void Print(struct Stu s2)
{
printf("%s, %hd, %s, %d\n", s2.name, s2.age, s2.sex, s2.id);
}
int main()
{
struct Stu s1 = { "William", 21, "male", 386910};
Print(s1);//传值调用
return 0;
}
传址调用:
我们把s1的地址传过去,用指针接收,理所应当打印的时候需要用解引用(*)操作符
我们也可以用(->)箭头指向要打印的成员
struct Stu
{
char name[20];
short age;
char sex[5];
int id;
};
void Print(struct Stu* s2)
{ //结构体变量.成员
printf("%s, %hd, %s, %d\n", (*s2).name, (*s2).age, (*s2).sex, (*s2).id);
//结构体变量->成员
printf("%s, %hd, %s, %d\n", s2->name, s2->age, s2->sex, s2->id);
//两种打印方式效果相同
}
int main()
{
struct Stu s1 = { "William", 21, "male", 386910};
Print(&s1);//传址调用
return 0;
}
问:上面两种方式哪个好些?
答案是:传址调用
总结:
函数传值过去要压栈,需要再copy一份结构体,如果结构体比较大,数据比较多,内存压力就会比较大,导致性能下降
传址过去是直接把地址交给指针变量,一个指针大小无非是4/8个字节