【结构体类型——详细讲解】

结构体

1.结构体类型声明

1.1结构体的概念

结构体是⼀些值的集合,这些值称为成员变量。结构体的每个成员可以是不同类型的变量。

1.2 结构的声明

struct tag
{
   
member-list;
}variable-list;

例如描述⼀个学⽣:

struct Stu
{
   
char name[20]; //名字
int age; //年龄
char sex[5]; //性别
char id[20]; //学号
}; //分号不能丢

1.struct是结构体的关键字,不可更改。
2.tag是结构体的名字,或者标签,可以更改。
3.member-list 结构体的成员列表,表示结构体内部的元素。
4.variable-list 结构体的变量成员列表,表示类型是结构体的变量,可以省略。

声明只是表示结构体的类型,并不占内存的空间,只有结构体变量初始化或者进行改变的时候,才会占用内存空间。

1.3特殊声明

在声明结构的时候,可以不完全的声明。
⽐如:

//匿名结构体类型
struct
{
   
int a;
char b;
float c;
}x;
struct
{
   
int a;
char b;
float c;
}a[20], *p;

上⾯的两个结构在声明的时候省略掉了结构体标签(tag)。

那么问题来了?

//在上⾯代码的基础上,下⾯的代码合法吗?
p = &x;

警告:

编译器会把上⾯的两个声明当成完全不同的两个类型,所以是⾮法的。
匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使⽤⼀次。

1.4 结构的自引用

在结构中包含⼀个类型为该结构本⾝的成员是否可以呢?
拿数据结构中的顺序表举例,自引用就是当你找到一个数字1的时候,你可以通过数字1顺藤摸瓜找到数字2,又可以从数字2顺藤摸瓜找到数字3,以此类推。
在这里插入图片描述
而结构体的自引用也是如此,不过其本身应该更类似与数据结构体中的链表。
在这里插入图片描述
通过1找到2,通过2找到3,通过3找到4,通过4找到5,这其中的每一个数字都是一个节点,这一个节点包含着前往下一个节点的线索,以此类推便可以顺藤摸瓜找到最后。

换到结构体身上便是一个结构体中包含着下一个结构体,且两个结构体是相同类型的,同名同标签(名 = 标签,不是变量名是结构体名)

那就有了下面的代码

⽐如,定义⼀个链表的节点:

struct Node
{
   
int data;
struct Node next;
};

上述代码正确吗?如果正确,那 sizeof(struct Node) 是多少?
仔细分析,其实是不⾏的,因为⼀个结构体中再包含⼀个同类型的结构体变量,这样结构体变量的⼤⼩就会⽆穷的⼤,是不合理的。

正确的自引用方式:

struct Node
{
   
int data;
struct Node* next;
};

根据链表的特点,我们将节点分为两个部分,一个部分存放的结构体本身的数据,另一个部分存放了下一个同类型同名的结构体的地址,这样便很好的解决了问题。

在结构体⾃引⽤使⽤的过程中,夹杂了typedef对匿名结构体类型重命名,也容易引⼊问题,看看下⾯的代码,可⾏吗?

typedef struct
{
   
int data;
Node* next;
}Node;

答案是不⾏的,因为Node是对前⾯的匿名结构体类型的重命名产⽣的,但是在匿名结构体内部提前使
⽤Node类型来创建成员变量,这是不⾏的。

解决⽅案如下:定义结构体不要使⽤匿名结构体了

typedef struct Node
{
   
int data;
struct Node* next;
}Node;

2.2. 结构体变量,全局变量、局部变量:

2.1结构体变量的创建和初始化

有了结构体类型,那如何定义变量,其实很简单,结构体变量的初始化使⽤

结构体初始化

struct Peo
{
   
   char name[20];
   char tele[12];
   char sex[5];
   int high;
};
 
int main()
{
   
 
  struct peo p = {
   "张三","15596668862", "男", 181};
  return 0;
}

包含了其他结构体变量的初始化:

struct Peo
{
   
   char name[20];
   char tele[12];
   char sex[5];
   int high;
};
 
struct st
{
   
   struct peo p;
   int num;
   float f;  
};
 
int main()
{
   
 
  struct s
  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值