目录
注:
本笔记参考B站up鹏哥C语言的视
结构体的声明
结构的基本知识
||| 就如同数组是相同类型的元素的集合,结构也是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。(方便描述复杂对象)
结构的声明
struct tag
{
member-list;
}variable-list;
如:描述一个学生
struct Stu
{
//成员变量
char name[20];//描述名字
int age;//描述年龄
char id[20];//描述学号
}s1, s2;
int main()
{
struct Stu s;//对象
return 0;
}
ps:
- 当输入[struct stu 变量名;]时,就(用类型)创建了一个对象。
- s1和s2也是结构体变量
- s1和s2是全局变量,而s是局部变量
结构成员的类型
结构成员可以是标量、数组、指针,甚至是其它结构体。
如:
struct B
{
char c;
short s;
double d;
};
struct Stu
{
char name[20];
int age;
char id[20];
struct B a;
}s1, s2;
结构体变量的定义和初始化
结构体的初始化
例
引用前述例子:
int main()
{
struct Stu s = { {'w', 20,3.14},"名字",30,"20202020" };//对象
return 0;
}
这就是结构体的初始化。(因为结构体内还有一个结构体,所以再使用一个{ })
各种结构体初始化的总结
struct Point
{
int x;
int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量的同时赋初值
struct Point p3 = { 2, 3 };
struct Stu
{
char name[15];
int age;
};
struct Stu s = { "名字",20 };//初始化
struct Node
{
int data;
struct Point p;
struct Node* next;//结构体指针
}n1 = { 10,{4,10},NULL };//结构体嵌套初始化
struct Node n2 = { 20,{5,6},NULL };//结构体嵌套初始化
结构体成员的访问
点操作符( . )
结构体变量的成员是通过点操作符( . )访问的。点操作符接受两个操作数。
如:
struct B
{
char a;
int b;
};
struct Stu
{
struct B b1;
char name[20];
int age;
};
int main()
{
struct Stu s1 = { {'w',2},"name",10 };
printf("%c\n", s1.b1.a);
printf("%d\n", s1.age);
printf("%s\n", s1.name);
return 0;
}
->的使用
如果想要通过指针访问结构体成员,要怎么做?
解引用的方式
struct Stu* ps = &s1; printf("%c", (*ps).b1.a);
->的使用方式
printf("%c\n", ps->b1.a);
这种方法也可以访问到a,打印结果为:w
结构体传参
引用[->的使用]中使用的结构体及其变量。
void print1(struct Stu t)
{
printf("%c %d %s %d", t.b1.a, t.b1.b, t.name, t.age);
}
void print2(struct Stu* ps)
{
printf("%c %d %s %d", ps->b1.a, ps->b1.b, ps->name, ps->age);
}
int main()
{
struct Stu s1 = { {'w',2},"name",10 };
//写一个函数打印s的内容
print1(s1);
printf("\n");
print2(&s1);
return 0;
}
[print1(s1);] 传值调用
[print2(&s1);] 传址调用
[print2]的优点:
- 可以改变原变量s1 - 功能更丰富
- 初始传参时,参数是需要压栈的。如果传递一个结构体对象时,结构体过大,参数压栈的开销比较大,会导致性能的下降。(浪费时间和空间)
知识点 - 压栈
推荐了解:函数栈帧的创建和销毁
函数调用的参数压栈:
栈,是一种数据结构:先进的后出,后进的先出。
解释
当输入数据时:
1. 当放入 1 这个数字时,1 是从顶部放入,放到底部向上的第一个位置上
2.当放入 2 这个数字时, 2 从顶部放入,放到底部向上的第一个位置上
……
从顶部放入数据的这种操作就叫做压栈。
当删除数据时:
底部的 1 够不到,要删除数据,得先删除 5
1.删除5
2.删除4
……
这种删除数据的操作就是出栈。
例如
Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 3;
int b = 5;
int c = Add(a, b);
return 0;
}
复习:每一个函数的调用,都会在内存的栈区上开辟一块空间。
在这之中,栈区:
· 创建 main函数,main函数 分配一块空间。
· 分配给 main函数 后,main函数 再划分空间,如:
接下来Add函数即将执行,需要传参。(大部分情况下[Add(a, b)]内部是从右向左传参的)
先传b
再传 a
函数的参数传参也称函数的压栈操作
Add函数被调用,在栈区内为Add函数开辟一块空间
在Add函数执行时:
此时,访问 x 和 y ,其实是访问 a' 和 b'
当调用完Add函数时,空间被返回。