目录
为什么有结构体变量?
在C语言中,对于数据而言我们有常见的:整型、字符型、浮点型等等种类。它们用来表示现实生活中的各种数值数据,但以上的类型定义时,或是定义单个变量,或是定义整体的一组变量——也就是数组。但生活中描述一个整体概念时候,不可能只用单一变量来定义,当你描述一个人时,我们需要包含:身高、名字、年龄、性别等等多个信息。可以看出我们需要不止一种类型变量来描述。所以我们便需要引进一下新的知识——结构体
C数组允许定义可存储相同类型数据项的变量,而结构体是C编程中另一种用户自定义的可用的数据类型,它是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。结构体也被称为“结构”
1.1 结构的声明
struct tag
{
member-list;
}variable-list;//结构体变量(列表),这里定义的是全局变量。
struct是结构体关键字,tag是结构体标签,这时 struct tag便是我们的结构体类型,类似于整型类型int 浮点型类型float一样。因为结构体是一个集合,所以我们使用大括号来囊括其中的成员——member-list,这里的成员可以是变量、数组、指针、结构体。但注意不可以是函数。括号外的则是结构体变量列表——variable-list。类比于int a;struct tag便是int,而variable便是a。(注意不要忘记分号哦)
1.2 结构体的定义和初始化
(1).结构体有两种定义方式,我们先来介绍第一种:声明后直接定义。
struct Student
{
char name[20];//学生名字
char sex[5];//学生性别
int age;//年龄
float height;//身高(单位m)
}s1;
可以如上代码显示,我们定义的struct Student是结构体类型,s1为结构体变量,这个s1变量有四个成员变量:名字、性别、年龄、身高四种。而有了变量我们便要对其初始化,就像int a =0;效果一样。但全局变量很容易被修改,所以我们不建议使用。
(2).接下来我们介绍第二种结构体变量的定义:先声明,再定义
int main()
{
struct Student s1 ;
return 0;
}
有了变量后,我们时常建议初始化该变量,结构体也不例外,我们这里用第二种定义方式来初始化,第一种同理。
struct Student s1 = {"小明","男",18,1.82};
在vs上我们可以观察其内存情况如下:
1.3结构体成员的访问
一个变量创建并初始化后,我们都可对其进行访问,结构体成员也不例外。对于一个结构体变量而言,我们需要用到(.)操作符和(->)操作符来访问其中变量。
(1),我们先来介绍(.)操作符的使用情况
我们的(.)操作符接收两个操作数,结构体变量名.结构体成员。例子如下:
int main()
{
struct Student s1 = {"张三","男",18,1.82};
printf("%s\n", s1.name);
printf("%s\n", s1.sex);
printf("%d\n", s1.age);
printf("%lf\n", s1.height);
return 0;
}
可当我们有时接收的不是结构体变量,而是一个指向结构体的指针呢?那便用到我们的(->)操作符结构体指针->结构体成员
void print(struct Student* p1)
{
//1.
printf("name=%s age=%d\n",(*p1).name,(*p1).age);
//2.
printf("name=%s age=%d\n", p1->name, p1->age);
}
int main()
{
struct Student s1 = {"小明","男",18,1.82};
print(&s1);
return 0;
}
我们先看print函数中的第一个打印,函数接收的是&s1,传进函数的也会是一个地址——也就是结构体的地址,所以我们只需要解引用该指针变量便可得到原本的结构体,然后使用(.)操作符便可成功访问其中的成员。
观察第二个打印,我们并没有解引用该结构体指针变量,直接用了(->)操作符来访问该结构体变量,就相当于我们使用结构体指针名,然后箭头到需要访问的变量中,便可成功的访问该结构体成员。如图下可以观察到两种访问方式均正确。
1.4 结构体的传参
与我们接触的一维数组传参类似——1.直接传递数组,2.传递数组地址。
结构体也有两种传参
1.结构体直接传参
2.结构体的指针传参
void print1(struct Student s1)
{
printf("name=%s age=%d\n", s1.name, s1.age);
}
void print2(struct Student* p1)
{
printf("name=%s age=%d\n", p1->name, p1->age);
}
int main()
{
struct Student s1 = {"小明","男",18,1.82};
print1(s1);
print2(&s1);
return 0;
}
print1是传递结构体s1,而print2传递结构体指针,两种传参方式对比一下,我们优先选用指针传参
因为函数传参的时候,参数是需要压栈的。如果传递一个结构体对象的时候,参数结构体过大,参数压栈的系统开销比较大,会导致性能下降。传递地址时,我们不需要为形参开辟新的空间,加快性能,并且址传递可以轻松改变结构体的数据。压栈的相关知识小编建议读者可以搜索了解相关知识,小编在这不做赘述。好啦,这篇文章便以这里结束咯,希望读者支持一下。