- 1.结构体的声明
- 1.1 结构的基础知识
- 1.2 结构的声明
- 1.3 结构成员的类型
- 1.4 结构体变量的定义和初始化
- 2.结构体成员的访问
- 2.1 结构体变量访问成员
- 2.2 结构体指针访问指向变量的成员
- 3.结构体传参
结构是一些值的集合,这些值称为成员变量。例如数组是一组相同类型元素的集合,但是结构的每个成员可以是不同类型的变量。
C语言内置了一部分内置类型,例如int,char,short,int,long long,double等;能够描述一些简单的事物,但是我们日常生活中有很多复杂的事物,例如人,一本书,人:名字+电话+性别+身高,书:书名+作者+定价+书号。这时候单个类型就无法描述,我们就可以利用结构体。
1.2 结构的声明//声明的结构体类型struct tag struct tag//tag是结构体标签 { member-list;//成员变量 }variable-list;//变量列表,可有可无
例如描述一个学生:
struct Stu { char name[20];//名字 int age;//年龄 char sex[5];//性别 char id[20];//学号 };//分号不能丢
例如描述一本书:
struct Book { char name[20];//名字 int price;//价格 char writer[10];//性别 char id[20];//书号 }b1,b2;//b1,b2是使用struct Book结构类型创建的2个全局的结构体变量 int main() { struct Book b3 = {0};//结构体变量的创建,b3是局部变量 return 0; }
结构体类型就相当于图纸,结构体变量就相当于房子,类比java中的类和对象思想,就像图纸并未占据空间,而房子是占据空间;结构体类型只是一个模板,并没有占据内存空间,只有创建的结构体变量才占据了一定的内存空间。
1.3 结构成员的类型结构的成员可以是标量、数组、指针,甚至是其他结构体。
sturct At { int arr[20]; int* pa; }; struct St { struct Peo p; int num; float f; }; struct Node { int data; struct Point p; struct Node* next; }n1;1.4 结构体变量的定义和初始化
有了结构体类型,我们可以直接创建结构体变量,并且对结构体变量进行初始化。
struct Peo { char name[20]; char tele[12]; char sex[5]; int height; }p3,p4; struct Peo p5,p6; struct St { struct Peo p; int num; float f; }; struct Node { int data; struct Point p; struct Node* next; }n1 = {10, {4,5}, NULL}; //结构体嵌套初始化 int main() { //初始化的顺序要于结构体类型的成员变量一一对应 struct Peo p1 = {"zhangsan", "13503532463", "男", 190}; struct St s = {{"lisi","15235335492","女",168}, 100, 3.14f}; return 0; }2.结构体成员的访问 2.1 结构体变量访问成员
结构变量的成员是通过点操作符(.)访问的。点操作符接受两个操作数。 例如:
struct Peo { char name[20]; char tele[12]; char sex[5]; int height; }; struct St { struct Peo p; int num; float f; }; int main() { struct Peo p1 = {"zhangsan", "13503532463", "男", 190}; struct St s = {{"lisi","15235335492","女",168}, 100, 3.14f}; printf("%s %s %s %dn",p1.name, p1.tele, p1.sex, p1.height);//结构体.成员变量 printf("%s %s %s %d %d %fn",s.p.name, s.p.tele, s.p.sex, s.p.height, s.num, s.f); return 0; }
运行结果:
2.2 结构体指针访问指向变量的成员有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针。那该如何访问成员。 如下:
struct Peo { char name[20]; char tele[12]; char sex[5]; int height; }; struct St { struct Peo p; int num; float f; }; void print1(struct Peo* p) { printf("%s %s %s %dn", p->name, p->tele, p->sex, p->height);// 结构体指针->成员变量 printf("%s %s %s %dn", (*p).name, (*p).tele, (*p).sex, (*p).height);// *(结构体指针).成员变量 } void print2(struct St* s) { printf("%s %s %s %d %d %fn", (*s).p.name, (*s).p.tele, (*s).p.sex, (*s).p.height, (*s).num, (*s).f); printf("%s %s %s %d %d %fn", s->p.name, s->p.tele, s->p.sex, s->p.height, s->num, s->f); } int main() { struct Peo p1 = { "zhangsan", "13503532463", "男", 190 }; struct St s1 = { {"lisi","15235335492","女",168}, 100, 3.14f }; print1(&p1); print2(&s1); return 0; }
运行结果:
3.结构体传参直接上代码:
struct S { int data[1000]; int num; }; struct S s = {{1,2,3,4}, 1000}; //结构体传参 void print1(struct S s) { printf("%dn", s.num); } //结构体地址传参 void print2(struct S* ps) { printf("%dn", ps->num); printf("%dn", *(ps).num); } int main() { print1(s); //传结构体 print2(&s); //传地址 return 0; }
上面的 print1和 print2函数哪个好些?
答案是:首选print2函数。
原因:
函数传参的时候,参数是需要压栈的。 你传递结构体作为参数,传递的其实是结构体的一份临时拷贝,如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统空间开销比较大,并且时间耗费严重,所以会导致性能的下降。而我们传递结构体地址(指针)作为参数,传递的其实是结构体所占空间的地址,地址的大小无非是4/8字节,空间较小,指针会指向地址所在的空间进行访问,并且还可以更改结构体。
结论: 结构体传参的时候,尽量传结构体的地址。