兄弟盟这篇文章我们来讲一下结构体。
首先呢我们还是要先讲一下什么是结构体:
1.1结构体类型的声明
1.1.1什么是结构体:
结构体(Struct)是一种自定义的数据类型,它允许将多个不同类型的变量组合在一起形成一个单一的类型。在编程中,结构体通常用于将相关的数据项组织在一起,以便于管理和操作。
结构体的定义通常包括以下几个部分:
1. 结构体名称:这是结构体的标识符,用于在代码中引用该结构体。
2. 成员变量:这些是结构体内部的变量,每个成员变量都有自己的类型和名称。
例如,在C语言中,一个简单的结构体定义可能如下所示:
struct Person {
char name[50];
int age;
float height;
};//分号不能丢
在这个例子中,`Person` 是结构体的名称,它包含三个成员变量:`name`(一个字符数组),`age`(一个整数),和 `height`(一个浮点数)。
使用结构体的好处包括:
- **数据封装**:将相关数据封装在一起,便于管理和维护。
- **代码清晰**:通过使用结构体,代码的逻辑更加清晰,易于理解。
- **类型安全**:结构体可以定义为特定的数据类型,编译器可以检查类型错误。
在实际编程中,结构体可以用于多种场景,如定义一个日期结构体来存储年、月、日信息,或者定义一个坐标结构体来存储x和y坐标等。结构体是编程中组织数据的重要工具之一。
1.1.2结构体变量的创建和初始化
关于结构体变量的创建这里有几种情况:
struct Book
{
char name[20];
char author[20];
float price;
char id[13];
}b3,b4;//全局变量
struct Book b2;//局部变量
int main()
{
struct Book b1;//局部变量
struct Book arr[5];//数组
}
那怎么么进行初始化呢?看下面:
#include <stdio.h>
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
};
int main()
{
//按照结构体成员的顺序初始化
struct Stu s = { "张三 ", 20, "男", "20230818001" };
printf("name: %s\n", s.name);
printf("age : %d\n", s.age);
printf("sex : %s\n", s.sex);
printf("id : %s\n", s.id);
//按照指定的顺序初始化
struct Stu s2 = { .age = 18, .name = "lisi", .id = "20230818002", .sex =
"女" };
printf("name: %s\n", s2.name);
printf("age : %d\n", s2.age);
printf("sex : %s\n", s2.sex);
printf("id : %s\n", s2.id);
return 0;
}
1.2结构的特殊说明
在声明结构的时候,可以不完全的声明。
比如:
//正常来说结构体是要有名字的,就想这样
struct S//这个S就是这个结构体的名字
{
char c;
int i;
double d;
};
int main()
{
struct S s;//这里可以进行创建变量。
return 0 ;
}
//但是对于匿名结构体呢?
//匿名结构体就是没有这个名字,当你把下面创建变量的的名字也去掉的话,那么下面也就不能直接创建变量了。
struct
char c;
int i;
double d;
}s = {'x',100,3.14};这时变量的名字就是在这里直接创建的,并且也可以初始化,下面也是可以正常打印的
int main()
{
printf("%c %d %lf\n",s.c,s.i,s.d)
return 0 ;
}
//这就是匿名结构体类型,匿名结构体类型只能用一次。
匿名结构体类型还有一个问题
struct
char c;
int i;
double d;
}s//你命结构体变量
struct
char c;
int i;
double d;
}*ps//匿名结构体指针。这两个结构体成员一模一样,但是ps不等于&s,就因为是匿名的
//这两个是不相等的
其实匿名结构体类型也是可以重新产生一个名字的:
//就想这样
typedef struct
{
char c;
int i;
double d;
}S;//这个S就是这个结构体的名字
int main()
{
S s;
return 0;
}//但是给一个匿名结构体起一个名字多多少少有点不伦不类了。
1.3结构的自引用
在结构中包含一个类型为该结构体本身的成员是否可以呢?
就像这样,定义一个链表的节点:
这里我们来说一下,什么是链表?什么是节点?
如图所示:像链条一样把每个数串起来就是链表,他是一种线性数据结构,而这每一个数就是一个节点,而这个节点不仅仅能携带一个数值,还要找到下一个节点,那我们把链表节点定义写成这样可以吗?
struct Node
{
int data;//这个节点携带的数据
struct Node next;//而且还携带者下一个数据
};
上述代码其实是不正确的,仔细分析,我们可以这样理解,sizeof(struct Node)是多大?因为一个结构体中包含一个同类型的结构体变量,这样结构体变量的大小就会是无穷大,是不合理的。
我仅仅是想找到下一个节点,那怎么弄?我们可以这样理解,在节点中存放一个整型并且也存放下一个节点的地址,让一个节点存放两个东西。那么最后一个节点地址处就存放空指针就可以了,这样就ok了。就想这样:
struct Node
{
int data;//数据
struct Node* next;//指针
};
int main()
{
return 0;
}
正确的就是这样啦, 这才是自引用。
typedef struct Node
{
int data;
struct Node* next;
}Node;//重命名
int main()
{
Node n2;这样写更简单一点,如够你不这样写,按原先的写法就是下面的会挺麻烦的。
return 0;
}
struct Node
{
int data;
struct Node* next;
};
int main()
{
struct Node n2;//这样写你每一次进行定义一个变量的时候都要把struct Node写一边,会很麻烦。
return 0;
}
//最上面的那串代码还可以写成这样。
struct Node
{
int data;
struct Node* next;
};
typedef struct Node Node;//这样进行重命名也是可以的。
int main()
{
Node n2;
return 0;
}
这里补充一点:匿名的结构体是不能实现结构体的自引用的效果。
OK了兄弟们,这就是今天的内容。