07结构体.
Posted 再吃一个橘子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了07结构体.相关的知识,希望对你有一定的参考价值。
目录
1.本章重点
结构体类型的声明
结构体初始化
结构体成员访问
结构体传参
2.结构体的声明
2.1结构的基础知识
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
比如说:人,或者书📕是一个复杂对象,属性不止一个,所以就构成了成员变量。
//定义一本书
struct Book
{
char name[20];
char autor[20];
float price;
};
//定义一个坐标
struct Point
{
int x;
int y;
};
注意:
这些都是结构体类型,并没有创建变量,所以没有占用空间。
2.2结构体的声明
struct tag//struct 名字
{
member - list;//成员变量列表
}variable - list;//结构体类型创建的变量
我们看着貌似和刚刚我们创建的书📕和坐标这种结构体定义有所不同,即:在最后的分号之前多了个东西,那是什么意思呢?
我们来对比思考一下,其实啊,这两种写法本质上是一样的,只不过一个是全局变量,一个是局部变量。
//定义一本书
struct Book
{
char name[20];
char autor[20];
float price;
};
int main()
{
struct Book b1;//结构体类型struct Book创建的局部变量b1
struct Book b2;//结构体类型struct Book创建的局部变量b2
}
//定义一本书
struct Book
{
char name[20];
char autor[20];
float price;
}b1, b2; //结构体类型struct Book创建的全局变量
int main()
{
}
两种写法都可以,不过是一个局部变量一个全局变量,一个放在内存的栈区一个放在内存的静态区罢了。
比如说我们用结构体定义声明一个学生,我们可以这样写:
struct Stu
{
char name[20];
int age;
char id[20];
};
int main()
{
struct Stu a;//定义一个学生a
return 0;
}
我们有时候在main()函数中嫌struct Stu结构体类型来定义变量,过于冗余,一般会用重命名的方式再来把struct Stu这个结构体类型重新命名一下,比如:
typedef struct Stu
{
char name[20];
int age;
char id[20];
}Stu;
int main()
{
Stu a;
return 0;
}
注意:
此处新定义的Stu不是变量哈,和刚刚的全局变量不一样哟~,此处新定义的Stu仍然是结构体类型struct Stu,只不过我们觉得冗余换了种写法,用typedef来重命名一下罢了~~
2.3结构成员的类型
结构的成员可以是标量、数组、指针,甚至是其他结构体。
3.结构体变量的定义和初始化
有了结构体类型,那如何定义结构体变量?其实很简单。
3.1结构体变量的定义
struct Point
{
int x;
int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
3.2结构体变量的初始化
struct Point
{
int x;
int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量的同时赋初值。
struct Point p3 = { x, y };
注意:结构体变量初始化,赋的初值是与结构体中的类型顺序相对应,且类型对应的。
那如果我们结构体中又嵌套一个结构体呢?改如何赋予初值??
struct S
{
int a;
char c;
double d;
};
struct T
{
struct S s;
char name[20];
int num;
};
int main()
{
struct T t = { {2,'100',3.14},"张三",6 };
return 0;
}
4.结构体成员的访问
结构变量的成员是通过点操作符(.)访问的。 点操作符接受两个操作数。
struct S
{
int a;
char c;
double d;
};
struct T
{
struct S s;
char name[20];
int num;
};
int main()
{
struct T t = { {2,'m',3.14},"张三",666 };
printf("%d % c %f %s %d", t.s.a, t.s.c, t.s.d, t.name, t.num);
return 0;
}
注意:
t的成员变量中含有struct S s这个结构体,中间仍然需要(.)先来访问t中的s,然后再用(.)来访问s中的成员变量。
在我的博客 05操作符和表达式 这一章节中,我们知道用地址同业可以访问成员变量,我们再来看一下叭~:
struct S
{
int a;
char c;
double d;
};
struct T
{
struct S s;
char name[20];
int num;
};
int main()
{
struct T t = { {2,'m',3.14},"张三",666 };
printf("%d % c %f %s %d\\n", t.s.a, t.s.c, t.s.d, t.name, t.num);
struct T* pt = &t;
printf("%d % c %f %s %d\\n", pt->s.a, pt->s.c, pt->s.d, pt->name, pt->num);
return 0;
}
在结构体访问成员变量中,我们需要注意:
- 如果我们是想通过地址来访问结构体中的成员,需要 ->
- 如果我们是想通过变量来访问结构体中的成员,需要 .
5.结构体传参
struct S
{
int a[100];
int num;
char ch;
double d;
};
void Print1(struct S ss)
{
printf("%d %d %d %d %d %c %lf", ss.a[0], ss.a[1], ss.a[2], ss.a[3], ss.num, ss.ch, ss.d);
}
int main()
{
struct S s = { {1,2,3,4,5,6},100,'w',3.14 };
Print1(s);
return 0;
}
我们看到,传参的时候,此时是值传递,即:将我们的结构体变量s,原封不动的copy一份,来实现打印,其实是非常浪费空间的。那么我们可以用地址来传递。
struct S
{
int a[100];
int num;
char ch;
double d;
};
void Print2(struct S* ss)
{
printf("%d %d %d %d %d %c %lf", ss->a[0], ss->a[1], ss->a[2], ss->a[3], ss->num, ss->ch, ss->d);
}
int main()
{
struct S s = { {1,2,3,4,5,6},100,'w',3.14 };
Print2(&s);
return 0;
}
上面的 Print1 和 Print2 函数哪个好些?
答案是:首选Print2函数
函数传参的时候,参数是需要压栈的。 如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。
举个好理解的栗子:
int Add(int x, int y)
{
int z = x + y;
return z;
}
int main()
{
int a = 10;
int b = 20;
int c = 0;
c = Add(a, b);
printf("%d", c);
return 0;
}
总结:
结构体传参的时候,要传结构体的地址。
以上是关于07结构体.的主要内容,如果未能解决你的问题,请参考以下文章