结构体的声明与自引用

今天上了数据结构课程的第一堂课,经常会看到下面这种语法:结构体有个成员变量是指向该结构体的指针,也就是自引用(self reference)。翻看了下一章节内容,才知道这是链表的结构基础。平时C语言用的比较少,借此机会重新复习了下结构体,在此记录相关知识。

结构体的声明

我们在定义结构体时,常常会用到两种方式。

方式1. 使用结构标签

用标签变量赋予结构体一个名字,这样定义结构体之后,可以用标签来声明结构体变量。

/*
**	标签(tag)为成员列表提供一个名字,可以在后续的声明中使用
**	下面这个声明,将标签PEOPLE与成员列表联系在一起(也就是定义了一个名为PEOPLE的结构体),
**	并声明了名为Man与Women的两个结构体变量
*/
struct PEOPLE	{
    int a;
    char b;
    float c;
}Man,Women;	//这里是声明的同时创建了两个变量。

/*
**	    变量的声明
**      声明变量时,需要在标签名前加上关键字struct
*/
struct PEOPLE Boy,Girl;	//声明了结构体变量 Boy 与 Girl

注意:声明结构体变量时一定要在前面加上struct关键字。但这样难免有些繁琐,所以大家都喜欢用下面介绍的方式2

方式2. 利用typedef技巧

/*
**	typedef用于定义一个新的类型名,可以认为是为结构体起一个别名
**	此段代码将原来的 struct PEOPLE 重新定义为类型people
*/
typedef struct PEOPLE{
    int a;
    char b;
    float c;
}people;	

/*
**	变量的声明
*/
people Women,Girl;    //声明了结构体变量 Women 与 Girl;
people Boy[20];       //声明了元素类型为结构体people的数组 Boy

可以看到,用typedef定义结构体后,结构体变量的声明变得十分方便。

结构体的自引用

结构体的自引用(self reference),就是在结构体内部,包含指向自身类型结构体的指针。这是实现链表结构的基础。

我们知道,顺序表的数据元素依次存放于一组地址连续的存储单元。而链表是用一组任意的存储单元来存放元素的,这些存储单元可以零散分布在内存的任何位置,大大提高存储器的使用效率。那么问题来了,既然存储单元地址不是连续的,那么前一个节点如何知道下一个节点的地址呢?这里就用到了结构体的自引用。在前一个节点(一个结构体变量)的成员变量中,把那个指针定义为下一个节点的地址,这样层层连接,实现了链表的存储。

但是,为什么定义结构体时,该成员变量是一个指针,而不直接声明该结构体自己呢?

https://blog.csdn.net/gzbaishabi/article/details/34926699

请看这篇文章,表述的非常好。

下面仍旧以两种结构体声明方式,分开讨论

方式1. 使用结构标签

错误的方式

/*
**	下面这种声明是错误的。
**	PEOPLE是一个结构体,成员变量b的仍旧是结构体
**	在分配内存时,由于无限嵌套,编译器无法确定PEOPLE的长度
*/
struct PEOPLE	{
    int a;
    struct PEOPLE b;
};			//非法

正确的方式

/*
**	由于指针的长度是确定的(指针长度为4),所以编译器能够确定该结构体的长度
*/
struct PEOPLE	{
    int a;
    struct PEOPLE *b;
};			

方式2. 使用typedef

错误的方式

/*
**	下面这种声明是错误的。
**	使用typedef时,程序执行到该段结束才完成了类型PEOPLE的定义
**	因此,虽然这里用了指针,但还是错误,因为还没完成类型的定义
*/
typedef struct{
    int a;
    struct people *b;
}people;		//非法

正确的方式

/*
**	利用结构标签进行指针的声明
*/
typedef struct tag{  
    int a;  
    struct tag *b;    
}people;

 

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值