编程时要用到C语言中结构体的自引用,由于用的少,学得时候也没在意,趁用到,回忆一下。

结构体的自引用(self

reference),就是在结构体内部,包含指向自身类型结构体的指针。

结构体的相互引用(mutual

reference),就是说在多个结构体中,都包含指向其他结构体的指针。

1. 自引用结构体

1.1

不使用typedef时

错误的方式:

struct tag_1{

struct tag_1

A; int value;

};

这种声明是错误的,因为这种声明实际上是一个无限循环,成员b是一个结构体,b的内部还会有成员是结构体,依次下去,无线循环。在分配内存的时候,由于无限嵌套,也无法确定这个结构体的长度,所以这种方式是非法的。

正确的方式: (使用指针)

struct tag_1{

struct tag_1 *A; int value;

};

由于指针的长度是确定的(在32位机器上指针长度为4),所以编译器能够确定该结构体的长度。

1.2 使用typedef

错误的方式:

typedef struct {

int value;

NODE *link; } NODE;

这里的目的是使用typedef为结构体创建一个别名NODEP。但是这里是错误的,因为类型名的作用域是从语句的结尾开始,而在结构体内部是不能使用的,因为还没定义。

正确的方式:有三种,差别不大,使用哪种都可以。

typedef struct tag_1{

int value;

struct tag_1 *link; } NODE;

struct tag_2;

typedef struct tag_2 NODE;

struct tag_2{

int value;

NODE

*link; };

struct tag_3{

int value;

struct tag_3 *link; };

typedef struct tag_3 NODE;

2. 相互引用 结构体

错误的方式:

typedef struct tag_a{

int value;

B *bp; } A;

typedef struct tag_b{

int value;

A *ap;

} B;

错误的原因和上面一样,这里类型B在定义之 前 就被使用。

正确的方式:(使用“不完全声明”)

struct tag_a{

struct tag_b *bp; int value;

};

struct tag_b{

struct tag_a *ap;

int value;

};

typedef struct tag_a A;

typedef struct tag_b B;

struct tag_a; struct tag_b;

typedef struct tag_a A;

typedef struct tag_b B;

struct tag_a{

struct tag_b *bp; int value;

};

struct tag_b{

struct tag_a *ap;

int value;

};

--------------------------------------------------------------------------------------

结构体的自引用中,如下这种情况是非法的

struct s_ref {

int a;

struct s_ref b;

char c;

};

因为结构体内部又包含自身结构体类型b,这个长度不能确定,只能向下再查找,又包含自身结构体类型b,又再向下查找,如此循环,类似于永无出口的递归调用,是非法的。

但很多时候,的确需要使用到自引用,有个技巧,如下:

struct s_ref {

int a;

struct s_ref

*b; //注意这句与上面相同位置的区别

char c;

};

这是合法的,因为此处是定义了一个指向结构体的指针,指针的大小在具体的机器平台和编译器环境中都是已知的(即使不同的平台环境的定义不完全相同)。所以不会导致上述的递归死循环。是合法和可行的。但是要提醒的是:这个指针看似指向自身,其实不是,而是指向同一类型的不同结构。

链表和树的数据结构就都使用到此技巧。自身的结构体指针指向下一节点或者下一子树的地址。

这里有一种情况值得注意:

typedef struct { //这里是结构体类型定义

int a;

s_ref

*b; //注意这句引用了结构体类型名

char c;

}s_ref ;

这个结构体类型定义是为了定义类型名s_ref,但却失败了。因为结构体中就引用了结构类型名,而此时还没定义类型名。

可以改为如下:

typedef struct s_ref_t{ //这里是结构体类型定义和结构体标签

int a;

struct s_ref_t

*b; //注意这句与上面相同位置的区别,使用了标签

char c;

}s_ref ;

这里将运行良好。

结构体嵌套结构体c语言,结构体的相互嵌套相关推荐

  1. c语言结构体嵌套及输出,C语言结构体嵌套

    C语言中的嵌套结构体表示在一个结构体中可以使用另一个结构作为成员.在C语言中定义结构体嵌套有两种方法: 通过独立的结构 通过嵌入式结构 1. 独立结构 我们可以创建2个结构体,但在主结构中应该使用依赖 ...

  2. c语言结构体共用体枚举实例程序,10-C语言结构体-共用体-枚举

    结构体是什么? 结构体和数组一样属于构造类型 数组是用于保存一组相同类型数据的,而结构体是用于保存一组不同类型的数组 定义结构体 在使用结构体之前必须先定义结构体类型,因为C语言不知道你的结构体中需要 ...

  3. c语言中定义结构体指针的作用,C语言结构体定义,使用及指针(1)

    前言 C语言中的结构体作为一大难点,并且对于需要学习数据结构的同学来说,这个结构是每次上课都会遇到的,所以,我们只有更深层次的理解结构体的知识,才能更好的掌握数据结构 结构体用处 结构体到底有什么用? ...

  4. c语言结构体的对齐方式,C语言结构体内存的对齐知识详解

    前言 在前面的章节中,我们谈到了C语言中整数以及浮点数的储存 今天,我们来谈一谈一些关于结构体内存的知识. 我们先来看一个例子: struct S1 { char c1; int i; char c2 ...

  5. c语言结构体调用成员函数,c语言结构体函数调用参数如何设置

    c语言结构体函数调用参数怎么设置 函数结构是下面的代码,main函数中如何调用showinfo函数,参数应该怎么设置,对参数的设置不太明白 C/C++ code#include #define SIZ ...

  6. linux中c语言结构体详解,Linux C语言结构体-学习笔记

    Linux C语言结构体简介 前面学习了c语言的基本语法特性,本节进行更深入的学习. 预处理程序. 编译指令: 预处理, 宏定义, 建立自己的数据类型:结构体,联合体,动态数据结构 c语言表达式工具 ...

  7. C语言结构体和链表结合,C语言结构体与链表

    C语言结构体与链表 第 10章 CHAPTER 10 结构体与共用体 学习目标 本章主要介绍结构体的定义和使用方法,然后介绍链表的概念和相关操作,最后介绍两种新的数据类型--共用体和枚举.通过本章的学 ...

  8. c语言结构体名称是什么,C语言结构体

    C语言结构体教程 结构体(struct)是由一系列具有相同 在 结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问. C语言结构体定 ...

  9. c语言结构体指针使用方法,C语言结构体指针的使用方法

    1.首先定义一个结构体,给它取别名: typedef struct node{ struct node * next://指向下一节点 int data://数据域 }pnode,*linklist; ...

  10. c语言中结构体变量的作用,C语言 结构体 类型变量的 定义 和 引用

    前面学习了变量和数组这些简单的数据结构,它们的特点是必须使用规定的数据类型.例如数组被定义为整型后,它的所有存储单元都是由整型构成.现实生活中某一类事物的共同属性可能是由不同的数据类型组成的集合,或者 ...

最新文章

  1. 深入探讨 java.lang.ref 包
  2. 各Rendering Path技术以及其在Unity中的实现
  3. LeetCode 2105. 给植物浇水 II(双指针)
  4. Struts2中UI标签之表单标签介绍
  5. Java读取Level-1行情dbf文件极致优化(2)
  6. 软件工程网络15个人阅读作业1(201521123062 杨钧宇)
  7. 阿里云:我们为全面服务政企市场做好了准备!
  8. 推荐一些逐步深入学习mysql的书籍
  9. MIMIC数据库数据提取教程-提取时间维度数据
  10. 【程序包uti1不存在怎么办?】求解答
  11. android 平板桌面,RUI平板桌面
  12. 输入法表情和小图标的应用
  13. redis统计用户日活量_使用redis统计用户日活、月活(实践版)
  14. Electron 打包Mac安装包代码签名问题解决方案
  15. c语言pop3,《ADOBE PHOTOSHOP CC标准培训教材》—第3章3.5节调整边缘
  16. 用html和css制作钟表,使用HTML5和CSS3制作简单的钟表
  17. Android 仿墨迹天气24小时预报
  18. python读取微信群信息_利用Python转发微信群通知信息
  19. 统计学专业未来从事大数据方向有优势吗?
  20. java递归实现汉字组词穷举_01背包各种算法代码实现总结(穷举,贪心,动态,递归,回溯,分支限界)...

热门文章

  1. Appium+python自动化(十六)- ADB命令,知否知否,应是必知必会(超详解)
  2. 08-可滚动Widget
  3. SecurityManager篇
  4. 2015软件测试面试题第二篇
  5. JPA与Hibernate的优缺点
  6. VS2010 工具箱组件添加重复
  7. struts2中action之间的一种跳转
  8. Java算法之寻找旋转数组中的最小值
  9. asp判断ajax请求 -asp.net,一个asp注册验证用户名是否重复的Ajax实例
  10. 从零开始学前端:grid布局和音频 --- 今天你学习了吗?(CSS:Day24)