结构体的声明
基础知识:
数组:一组相同类型元素的集合
结构体:也是一些值的集合,但是值的类型可以不同。
结构的成员可以是标量、数组、指针,甚至是其他结构体。
结构体在创建的时候实际上是创建了结构体类型语法:
struct 自定义结构体类型名{ 结构体成员表 }结构体变量表;
使用实例:
struct B { char c; short s; double d; };//分号不能丢 struct Stu//创建结构体类型 { //成员变量 struct B sb; char name[20]; int age; char id[20]; }s1, s2;//声明类型的同时定义s1和s2也是结构体变量,同时因为定义在花括号外,所以是全局变量 int main() { struct Stu s = { {'w',20,3.14},"张三",18,"20200543 " };//结构体嵌套初始化 //struct Stu 才是结构体类型,不能随便省略struct return 0; }
补充typedef
结构体类型的声明 typedef struct Stu { char name[20];//名字 int age;//年龄 char sex[8];//性别 float score; }Stu(重命名序列表); //实际上是等同于typedef struct Stu Stu; //原本的struct Stu类型重命名为了Stu类型。
结构体成员的访问
结构变量的成员是通过点操作符(.)访问的。
结构体指针访问指向变量的成员用->访问续上面的代码
printf("%c\n",s.sb.c);//点操作符访问 printf("%s\n",s.id); struct Stu* ps=&s;//定义指针变量 printf("%c\n",(*ps).sb.c);//解引用的访问访问 printf("%c\n",ps->sb.c);//sb不是指针,所以只能用.来访问
结构体传参
直接上代码:
struct B { char c; short s; double d; }; struct Stu { //成员变量 struct B sb; char name[20]; int age; char id[20]; }; void print1(struct Stu t ) { printf("%c %d %lf %s %d %s", t.sb.c, t.sb.s,t.sb.d,t.name,t.age,t.id); } void print2(struct Stu* ps) { printf("%c %d %lf %s %d %s", ps->sb.c,ps->sb.s,ps->sb.d,ps->name,ps->age,ps->id); } #include <stdio.h> int main() { struct Stu s = { {'w',20,3.14},"张三",18,"20200543 " }; //写一个函数打印s的内容 print1(s);//传值调用(更安全) print2(&s);//传址调用(效率更高,节约空间) return 0; }
print2函数更优的原因:函数传参的时候,参数是需要压栈的。 如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。
所以结构体传参的时候,要传结构体的地址。
函数调用的参数压栈
栈,是一种数据结构,先进的后出,后进的先出。
可以把栈看为一个四周密闭的盒子,从栈顶(盒子的上)往栈底(盒子底部)存放数据,给栈存放数据的过程就叫压栈。而出栈只能从顶部开始往下删除。举个例子:
int Add(int x, int y)//5.又找了一块区域分配给了Add { int z = 0;//在Add的空间底部存放z z = x + y;//然后将x,y相加的结果返回给z return z;//返回z //6.返回的时候就开始销毁这块内存空间,从上往下开始销毁,先销毁Add的空间,然后销毁形参的空间。 } #include <stdio.h> //1.每一个函数调用都会在内存的栈区上开辟一块空间 int main()//2.调用main函数实际上在栈区开辟了一块空间 { int a = 3;//3.在main的空间底部开始存放数据 int b = 5; int c = 0; c = Add(a,b);//4.函数传参通常情况是从右向左传的,所以先为b开辟一块空间,然后在b的上面为a开辟一块空间,函数传参的这个操作和压栈很相似,所以也叫压栈操作 return 0; }
描述有些抽象,看图就能很好的理解了:
本章完。愿你有所收获,如果再也不能见到你,也祝你早安午安,还有晚安。