前言:
在上章节讲解了浮点数在内存的储存,在本章节为大家讲解结构体。
一·结构体的概念
结构"是一种构造类型,它是由若干"成员"组成的,每一个成员可以是一个基本数据类型或者又是一个构造类型.
结构既是一种"构造"而成的数据类型,那么在说明和使用之前必须先定义它,也就是构造它,如同在说明和调用函数之前要先定义函数一样
结构体的定义使用struct
关键字,其基本语法如下:
struct 结构体名称 {
数据类型 成员1;
数据类型 成员2;
...
};
类比现实:想象学生档案,包含姓名(字符串)、学号(整数)、成绩(浮点数)。结构体能将这三个字段“打包”成Student
类型。
例如:
struct Student {
int id;
char name[50];
float score;
};
结构体的成员可以是基本数据类型,也可以是其他复杂数据类型,如数组、指针等。
二·结构体的声明与初始化
在C语言中,结构体可以通过以下方式声明和初始化:
仅声明结构体变量,但不初始化。
struct Student ;
初始化:在声明时直接赋值。
struct Student s = {1234, "张三", 100.0};
逐个成员赋值:
struct Student s2; s2.id = 1002; strcpy(s2.name, "Bob"); s2.score = 88.5;
三·结构体成员的访问
使用
.
操作符:struct Student *ptr = &s1; printf("Score: %.1f\n", ptr->score); // 输出92.5
使用.操作符后会出现这样的界面,供你选择,选择你想要输出的内容。
#include <stdio.h>
struct student
{
int id;
char name[40];
float score;
};
struct student s1 = { 1001, "Alice", 92.5 };
int main()
{
printf("%d %s %f", s1.id, s1.name, s1.score);
return 0;
}
指针使用->
操作符:
struct Student *ptr = &s1;
printf("Score: %.1f\n", ptr->score); // 输出92.5
四·结构的特殊声明
匿名结构体类型
不完全声明:
在声明结构体时,可以省略结构体标签,但必须在后面的大括号中给出成员定义。
例如:
struct //匿名结构体类型
{
int a;
char b;
float c;
}s1,s2,s3;
匿名结构体的限制:
匿名结构体只能在声明时直接使用,不能在其他地方引用或重复使用。
例如,以下代码是非法的:
struct {
int a;
char b;
} x;
struct {
int a;
char b;
} y = x; // 错误,x和y是不同的类型
编译器会将两个匿名结构体视为不同的类型,从而导致语法错误
五·结构体的自引用
自引用的定义:
自引用结构体的定义需要先声明一个结构体标签,然后在该结构体中定义一个指向该结构体的指针。
例如:
struct Node {
int data;
struct Node *next; // 自引用指针
};
这种方式合法,因为编译器在解析struct Node
时,已经知道Node
的完整结构,因此可以正确计算next
的长度。(PS:如何计算大小在下面会讲解的,稍安勿躁)
- 错误的自引用方式:
如果在结构体中直接包含一个未定义的结构体实例,会导致编译器无法确定其长度,从而引发错误。例如:
struct Node {
int data;
struct Node next; // 错误,未定义的结构体实例
};
这种写法会导致编译器无法计算出Node
的长度,因此是非法的。
自引用的注意事项
- 避免同时使用匿名声明和自引用:匿名结构体的最大特点是只能在声明时使用,而自引用需要在结构体定义完成后才能使用。因此,两者同时使用会导致矛盾,例如:
struct {
int a;
struct {
int b;
} *ptr;
} x; // 错误,ptr未定义
由于匿名结构体的限制,ptr
无法在声明时正确解析。
- typedef的使用:为了简化代码,可以使用
typedef
定义一个结构体别名,并在定义中包含自引用。例如:
typedef struct {
int data;
struct Node *next;
} Node;
总结:
本章讲解了结构体的运用和使用操作符,如何正确的初始化。
如果本章对大家有一点点的帮助,可以关注一下博主!!!