C语言 结构体

C 语言允许用户自己建立由不同数据组成的数据结构,称为结构体。

一、什么是结构体

在现实生活中,一个事物往往会多个属性,每个属性又对应一条数据,将这些数据组合成一个整体,便能够更好地使用。

例如:

学生(学号, 姓名, 性别, 年龄, 班级)

显然,这些数据无法通过数组存放,因为数组的每个元素都是同一类型的,而现实中一个事物对应的多个数据往往是不同类型的。

结构体便可以很好地解决这个问题,它允许用户自己建立由不同类型数据组成的组合型的数据结构。

二、声明结构体类型

1
2
3
struct 结构体名{
成员列;
};
  • struct 结构体名 为这个结构体的名字, struct 不可以省略

  • 在成员列中填入希望组成结构体的数据

例如:

1
2
3
4
5
6
7
struct Student{
int num;
char name[20];
char sex[20];
int age;
int class;
}

三、定义结构体变量

1.先声明类型,再定义变量

1
2
3
4
struct 结构体名{
成员列;
};
struct 结构体名 结构体变量名;

建立好结构体类型后,便可以像 int、double 那样,用 struct 结构体 定义对应类型的变量。

2.声明类型的同时定义变量

1
2
3
struct 结构体名{
成员列;
} 变量名列;

3.不声明类型,直接定义变量

1
2
3
struct{
成员列;
} 变量名列;

四、结构体变量的初始化

在定义结构体变量时,可以对它初始化,即赋予初始值。

1
struct 结构体名 结构体变量名 = {初值表列};
  • 可以对每个成员都初始化

    例如:

    1
    struct Student student1 = {001, "xiaowang", "boy", 21, 0301};
  • 可以只初始化部分成员

    例如:

    1
    struct Student student1 = {.name = "xiaowang"};
  • 未被初始化的数值将会是 0 ,字符将会是 ’\0‘ ,指针将会是 NULL

五、结构体变量的使用

1.访问成员

可以访问结构体的成员,并像普通变量一样参与运算。

1
结构体变量名.成员名

例如:

1
2
student1.num = 2;
printf("%s", students1.name);

2.结构体赋值

同类结构体可以进行整体赋值。

例如:

1
2
struct Student student1 = {001, "xiaowang", "boy", 21, 0301};
struct Student student2 = student1;

3.引用地址

可以引用结构体的地址,也可以引用结构体成员的地址。

例如:

1
2
printf("%p", &student);  //输出结构体的地址
scanf("%d", &student1.num);

六、结构体数组

一个结构体变量可以存放一组有关联的数组,但如果有多组数据,显然应该用结构体数组

1.定义结构体数组

1
2
3
struct 结构体名{
成员列;
}数组名[数组大小];
1
struct 结构体名 数组名[数组大小];

2.初始化结构体数组

1
struct 结构体名 数组名[数组大小] = {{初值表列1}, {初值表列2}, ···, {初值表列n}};

3.访问数组中的结构体

1
数组名[下标]

4.访问数组中的结构体成员

1
数组名[下标].成员名

七、结构体指针

1.指向结构体变量的指针

1
2
struct 结构体名 *指针名;
指针名 = &结构体变量名;

2.通过指针访问成员

1
(*指针名).成员名

等价写法

1
指针名->成员名

3.通过指针遍历结构体数组

1
2
3
4
5
struct 结构体名 数组名[数组大小];
struct 结构体名 *指针名= 数组名;
for (i = 0; i < 数组大小; i++, 指针名++){

}

八、结构体成员作为函数参数

访问结构体成员,并将其作为实参传入函数,与其它变量完全相同。

1
2
3
4
5
void fun(int n){

}
···
fun(student1.name);

九、结构体变量作为函数参数

1
2
3
4
5
void fun(struct 结构体名 形参名){

}
···
fun(结构体变量名);
  • 整个结构可以作为参数传入函数
  • 实际上是在进入函数时新建一个结构体变量,复制实参数据
  • 数据的传递是单向传递、值传递,因此在函数中的修改同样无法传递
  • 这种传递方式在空间和时间上的开销比较大
  • 结构体也可以作为返回值

十、结构体指针作为函数参数

用指向结构体变量的指针作为实参,将结构体变量的地址传给形参。在时间和空间上的开销较小,且在函数中的修改也可以传递回去。

十一、结构体数组作为函数参数

当作指针处理。

十二、结构体的嵌套

1.结构体中的结构体

1
2
3
4
5
6
7
8
struct Class{
参数表列;
};
struct Student{
int num;
char name[20];
struct Class class;
};

2.结构体中的结构体指针

1
2
3
4
5
struct Student{
int num;
char name[20];
struct Student *nextstu;
};

参考