此文是作者初次学习C语言的时候,写的笔记博文,如有错误请及时指正,谢谢!!!
目录
1,什么是结构体
2. 结构体的声明
2,1结构体声明
2,2结构体成员的类型
2,3结构体变量的定义的初始化
3. 结构体成员的访问
4. 结构体传参
5,拓展
1,什么是结构体
我们已经学过的数据类型有 char, int,long, short, long long, float, double,这些类型只能描述单一的对象,不能描述复杂的对象。 比如现在我们要描述一个学生类型的复杂对象,需要描述他的名字, 年龄, 性别, 成绩----。 我们就需要吧char类型的, int类型的, float类型的。整合到一起共同构成这个复杂对象。把这些单一对象和在一起就需要用到结构体。
结构是一些值的集合,这些值称为成员变量。结构的每一个成员可以是不同类型的变量。
2. 结构体的声明
2,1结构体声明
基本结构:
struct 结构体名
{
成员列表;
}变量列表;
这里struct 结构体名,共同构成了一个数据类型名。
//结构体类型的声明
struct stu//这里的struct是用来定义结构体//stu是结构体名(自定义的)
{char name;//名字int age;//年龄char sex[8];//性别float score;//分数};//注意这里有一个;
struct stu
{char name;int age;}s1, s2, s3;
//这里的s1,s2,s3是通过struct stu类型创建的变量
//可以写也可以不写,可以写一个也可以写多个。
//此时创建的s1, s2, s3,是全局变量。
//但是平时很少这样定义
同样结构体类型变量也可以在主函数内创建
int main()
{//在主函数内部也可以创建结构体变量struct stu s4;struct stu s5;//这里的s4, s5就是局部变量//struct stu整体才是结构体类型, 不能随便省略任何单个词//如果觉得结构体类型太长, 这里可以用到typedef//类型重定义或者类型重命名typedef struct stu stu;//把struct stu 重新起个名字叫stustu s5;stu s6;//这里经过类型重定义,就可以用自定义的类型名来创建变量s5,s6return 0;
}
类型重定义也有别的表示方式,例如在定义结构体的时候给它重命名。
typedef struct stu
{char name;int age;char sex[8];float score;
}stu;//然后以后就可以用 stu 来定义结构体变量。
2,2结构体成员的类型
结构的成员可以是标量,数组, 指针,甚至是其他结构体。
2,3结构体变量的定义的初始化
结构体变量的定义
struct Point {int x;int y; }p1; //声明类型的同时定义变量p1struct Point p2; //定义结构体变量p2
结构体变量的初始化
//简单结构体初始化 struct Point {int x;int y; }p1 = {100, 200};//用大括号来初始化struct Point p2 = { 100, 200 };
//复杂结构体的初始化 struct s {char a;struct point po;double b;char arr[10]; };//也是使用大括号来初始化 struct s ss = { 'w', {100, 200}, 1.1, "abcdef" };
//复杂结构体初始化 struct Node {int data;struct Point p;struct Node* next; }n1 = { 10, {4,5}, NULL }; //结构体嵌套初始化struct Node n2 = { 20, {5, 6}, NULL };//结构体嵌套初始化
3. 结构体成员的访问
这里就要用到结构体成员访问操作符 " . " 和 " -> " 。
看实例
struct stu {char name[30];int age;double score; };struct point {int x;int y; };struct test {int a;struct stu b;struct point c;char d; };#include<stdio.h>void print1(struct test tt)//传过来的是数据,实参把数据传给形参 {printf("%d\n", tt.a);printf("%s %d %lf\n", tt.b.name, tt.b.age, tt.b.score);printf("%d %d\n", tt.c.x, tt.c.y);printf("%c\n", tt.d); }void print2(struct test* tt)//传过来的是地址 {printf("%d\n", tt->a);printf("%s %d %lf\n", tt->b.name, tt->b.age, tt->b.score);printf("%d %d\n", tt->c.x, tt->c.y);printf("%c\n", tt->d);//注意这里不可以tt->b->name}int main() {struct test tt = { 1, {"张雪峰", 21,100.0}, {100, 200}, 'w' };//用”.“字符, 结构体变量.结构体成员print1(tt);//传值调用//用”->“字符//通常运用于结构体指针print2(&tt);//这里是传址调用。 结构体指针->结构体成员return 0; }
也可以通过访问符来修改数据
int main() {struct test tt = { 1, {"张雪峰", 21,100.0}, {100, 200}, 'w' };tt.a = 1000;strcpy(tt.b.name, "刘雪萍");tt.b.age = 20;tt.b.score = 99.0;tt.c.x = 10000;tt.c.y = 20000;tt.d = 'q';print1(tt);//打印return 0; }
4. 结构体传参
struct S
{int data[1000];int num;
};
struct S s = {{1,2,3,4}, 1000};//结构体值传参
void print1(struct S s)
{printf("%d\n", s.num);
}//结构体址传参
void print2(struct S* ps)
{printf("%d\n", ps->num);
}int main()
{print1(s); //传结构体print2(&s); //传地址return 0;
}
上面print1和print2函数显然第二个会更好一点
原因:
1,函数传参的时候,参数是需要压栈的。
2,如果传递的一个结构体对象的时候,结构体过于大,参数压栈的系统开销就比较大,所以会导致性能的下降。
结论:结构体传参的时候,要传结构体的地址。
5,拓展
内存被分为栈区, 堆区, 静态区。
栈区:局部变量, 函数的参数(形式参数)
堆区:动态内存开辟, mal loc, free loc, rea loc
静态区: 静态变量, 全局变量