此文是作者初次学习C语言的时候,写的笔记博文,如有错误请及时指正,谢谢!!!
目录
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 重新起个名字叫stu
stu s5;
stu s6;//这里经过类型重定义,就可以用自定义的类型名来创建变量s5,s6
return 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; //声明类型的同时定义变量p1 struct 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
静态区: 静态变量, 全局变量