一、结构体的声明
1. 结构体的基本概念
结构体是一些值的集合,这些值称为成员变量。结构体的每个成员可以是不同类型的变量。结构体使得C语言有能力描述复杂类型。
如学生,有姓名、学号、性别等;如书,有作者,出版日期,价格等
2. 结构体的声明
(1)声明格式为:
struct tag
{
member-list;
}variable-list;
其中member-list为结构体成员变量列表;variable-list为需要创建的结构体变量的列表
例如描述一个学生的结构体声明就可以写成:
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
};//分号不能丢
3. 结构体的成员类型
结构体的成员可以是标量、数组、指针,甚至是其他结构体
4. 结构体变量的定义和初始化
(1)定义
- 沿用上面描述学生的声明,声明一个结构体变量可以有两种方式:
声明类型的同时定义变量,即将变量名直接写在变量列表中;或者另起一行像定义其他类型变量一样定义结构体变量
如下面这段代码:
struct Stu
{
char name[20];
int age;
char sex[5];
char id[20];
}Stu1,Stu2; //声明类型的同时定义变量Stu1和Stu2
struct Stu Stu3; //另起一行定义结构体变量Stu3
注意这里另起一行定义结构体变量的写法与下面即将提到的另一种方式区别
- 还有一种定义方式,不过此时结构体声明部分与上面的略有不同,因为用到了
typedef
类型重命名关键字,代码如下:
typedef struct Stu
{
char name[20];
int age;
char sex[5];
char id[20];
}Stu;
注意这里最后的Stu不是上面说所的变量列表中的内容,即不是声明类型的同时定义的变量,而是这个结构体类型的一个重命名,此时定义一个结构体变量的正确写法就应为:Stu Stu4;
当然写成struct Stu Stu4;
也没错。但需要注意,上面没有用typedef关键字进行类型重命名的声明只能写成struct Stu 变量名;
而不能写成Stu 变量名;
(2)初始化
即定义变量的同时赋予初值
这里继续沿用上面学生的声明:
struct Stu
{
char name[20];
int age;
char sex[5];
char id[20];
}Stu1 = {"小明",16,"男","124410"} //声明类型的同时定义变量Stu1
struct Stu Stu2 = {"小红",16,"女","124450"};
//另起一行定义结构体变量Stu2
- 结构体的嵌套初始化:
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化
5. 补充说明
结构体的声明一般是放在主函数之外的,故声明类型的同时定义的变量一般为全局变量。虽然语法也允许结构体的声明放在主函数中,不过一般不这么做。
二、结构体成员的访问
1. 结构体变量访问成员
结构变量的成员是通过点操作符 ‘ . ’ 访问的。点操作符接受两个操作数,形式为结构体变量名.成员变量名
。如下面这段代码:
#include <stdio.h>
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}Stu1 = { "小明",16,"男","124410" };//分号不能丢
int main()
{
printf("%s\n", Stu1.name);
printf("%d\n", Stu1.age);
printf("%s\n", Stu1.sex);
printf("%s\n", Stu1.id);
return 0;
}
运行结果:
2. 结构体指针访问成员
有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针。
那么此时我们通过另一个操作符 ‘->’ 进行访问。如下代码:
#include <stdio.h>
struct Stu
{
char name[20];
int age;
};
void print(struct Stu* ps)
{
printf("name = %s age = %d\n", (*ps).name, (*ps).age);
//使用结构体指针访问指向对象的成员
printf("name = %s age = %d\n", ps->name, ps->age);
}
int main()
{
struct Stu s = { "zhangsan", 20 };
print(&s);//结构体地址传参
return 0;
}
运行结果:
代码中的print函数的参数是一个结构体指针,故在进行参数传递时传的是结构体的地址(下面一部分还会说明),那么在print函数内部进行的成员访问实际上是通过结构体指针进行的。所以用到操作符 ‘->’ 。
由运行结果可以看出,使用操作符 ‘->’ 就等价于先解引用结构体指针得到结构体变量,再通过操作符 ‘ . ’ 进行成员访问。
三、结构体的传参
结构体的传参和变量的传参一样,分为值传递和地址传递。结构体在进行传参时一般用的都是地址传递,即传递结构体的地址。
原因:函数传参的时候,参数是需要压栈的。如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。
本章完。
看完觉得有觉得帮助的话不妨点赞收藏鼓励一下,有疑问或有误地方的地方还恳请过路的朋友们留个评论,多多指点,谢谢朋友们!🌹🌹🌹