自定义类型:结构体(一)

 一 . 结构体的相关概念 

结构体,无需多言,是我们的老朋友了,我们之前就学习过一些有关结构体的知识,今天我们就来正式认识一下这个朋友

结构体属于一种自定义类型,在我们C语言中:自定义类型并非只有结构体这一种,还有联合体,枚举。今天我们着重来了解一下结构体

有的小伙伴可能发现了,结构体和我们学过的数组很像,的确是这样的,但是它俩又有着一些区别

数组:一个或者多个成员,元素类型必须相同

结构体:一个或者多个成员,元素类型可以不同

 二 . 结构体类型的声明 

(1)结构体的一般声明

那么我们结构体是怎样声明的呢?格式如下:

如图,大括号上方,struct tag 就是我们自定义的结构体类型,大括号里的就是成员列表,大括号下面的就是变量列表,我们的结构体便是由这三个部分组成。光看这个可能有些枯燥难懂,我们可以将其运用到实际例子当中去:

如图,咱们要用一个结构体来表示一本书的各项信息,我们就可以这样,成员列表里就是我们需要表示的这本书的各项信息:书名、作者、单价、编号等等。我们的结构体变量一次性可以不止一个,列如我这里的 b1、b2。由于结构体的声明是脱离我们的主函数 —— main()函数之外的,所以这里我们创建的结构体变量自然而然就是一个全局变量

这个时候就有同学会问了,那我们可不可以创建一个局部变量的结构体变量呢?答案是当然可以的,我们还有一种方法是当我们结构体在 main 函数内初始化的时候,这个初始化的同时也会创建结构体变量:

如图,我们在创建结构体类型的时候创建了两个变量:b1、b2,但并未初始化;我们又在 main 函数内创建了变量:b3、b4 并且初始化

由图可见,我在进行结构体的初始化时,用力两种方法,一种是我们正常的初始化,这个初始化必须是严格按照我们创建结构体成员列表时的顺序一对一进行初始化的;第二种方法就不想上面那样必须一个萝卜一个坑的去对照,我们只需要打出一个 . ,然后去选择我们相应的成员去进行初始化就完了

有图可知,我在打印结构体的时候也用了两种方式:

1 . 一种就是我们普通以 . 的方式

2 . 另一种则是我们指针的形式,我们将取出 b4 的地址赋给我们创建的结构体指针变量 ptr,然后在打印时用 “ ptr —> ”的方式,

注意:诸君可以发现,我们打印出来的单价并不是跟我们设定的价格一模一样,而是有一点误差,因为浮点数在内存中有可能是不能精确保存的,因此我们对于浮点数的比较一般也不用 “ = ”, 在上一章节咱们讲解过浮点数在内存中的存储,我相信诸君对于这一点应该不难理解,如果没看过的小伙伴起强烈建议去看一看前面的章节哦!

( 1 . 1 )浮点数之间大小的比较

这里再给大家拓展一个知识,就是我们浮点数大小的比较:

刚刚上面我说我们浮点数的比较一般不用等号 =,那我们要怎样才能进行浮点数之间的比较呢?

如图,咱们这里使用到了一个函数 —— fabs,这个表示的是浮点数的绝对值,还有一个 abs 就是整数的绝对值。咱们浮点数之间的比较用两个数作差的绝对值小于 0.000001(我们可接受的一个误差区间),这样子就可以基本确定我们两个浮点数的大小关系了

(2)结构体的特殊声明

在我们进行结构体声明时,还有一种还有一种特殊声明 —— 不完全声明(匿名结构体类型)

如图,以上就是我们匿名结构体类型的格式,诸君可见,匿名结构体类型就是:声明时省略掉了我们的结构体标签,且我们的匿名结构体声明只能用一次。第二个是我们创建了一个结构体指针变量,可以看到我们这两个结构体除了变量名可以说是一模一样的,那么这时候我想问大家一个问题:

在我们上面创建的两个结构体变量的基础上,ps = &s1 可行么?

答案是否定的,虽然我们两个结构体中的类型和成员一模一样,但是由于是匿名结构体,在系统看来这两个结构体的类型是不相同的,编译器会把上面两个声明当成完全不同的两个类型,所以这种操作是属于非法的

 三 . 结构体的自引用 

(1)结构体的一般自引用 

结构体的自引用,听到这个概念,我相信大多数小伙伴都会想起我们的函数递归之类的,没错,结构体的自引用就跟我们之前学过的函数递归是有着异曲同工之妙的

在讲结构体的自引用之前,我们先来引入一个概念 —— 链表

如图,当我们数据的存储在内存中是混乱的,我们需要将它们串联起来,我们将这样的形式就称为链表,我们结构体的自引用就可以这样模拟实现链表的表达形式,将这份数据放在一个结构体中,再对其自引用去找到下一份数据

我们先来举个例:

如图,我们在结构体中,相当于链表节点的形式,对我们的结构体进行自引用,让其自己找到下一个节点,再自引用,此番循环......这可以么?这是不行的,我们这个结构体内放了一个数据 data,还放了一个自己本身,因此这个结构体所占内存大小我们是无法确定的

正确的结构体自引用格式:

如图,我们换一种思路,换一种方式就可以了,这样子我们存放的是一个数据,这叫数据域,还有存放着下一个节点的地址,这叫指针域,通过这个地址去找到下一个节点,一个整型占 4 个字节,一个地址占 4 / 8 个字节,这样子我们结构体的大小就可以得到确定

这就是我们所谓的结构体的自引用,诸君明白了么?

(1)结构体自引用匿名结构体 

这里在深入一个问题:结构体在自引用的过程中,夹杂了 typedef 对匿名结构体类型的重命名,这种情况我们又应该怎样实现呢?大家思考一下我们依旧如下图这样可以吗?

答案是否定的,因为 Node 是对前面的匿名结构体类型重命名产生的,但是我们在匿名结构体内使用就属于提前使用了 Node 类型来创建成员变量,这当然是不行的,所以我们在结构体内部依然要使用完整的结构体类型:

以上就是我们有关结构体自引用的部分知识点

OKK,今天有关结构体的内容就说到这里啦,如果对各位小伙伴有所帮助,不妨点个关注,咱们下期再见吧,与诸君共勉!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/885085.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用匿名管道时出现程序一直运行问题

父进程创建两个子进程,父子进程之间利用管道进行通信。要求能显示父进程、子进程各自的信息,体现通信效果。(源程序pipe_1.c) 一开始,我忘了初始化pipe,很傻*的直接把fd当管道使,出现了儿子喊爸爸"i am your father."的…

协程4 --- 一个特殊的栈溢出例子

文章目录 代码运行结果分析 代码 先看下面这个程序流程: 有个长度位24的字符数组buffer,前面16个字符初始化。 把attack函数的地址复制到后面8个字符(编译成64位程序,指针大小为8Byte)。 打印信息:do Some…

C++用string实现字符串相加

. - 力扣(LeetCode) -》》》》》题目链接 实现思路:计算数字符串长度并用数组的方式计算出字符位置,用字符的ask码‘0’计算出字符本身。 class Solution { public:string addStrings(string num1, string num2) {string str;int…

03 Oracle进程秘籍:深度解析Oracle后台进程体系

文章目录 Oracle进程秘籍:深度解析Oracle后台进程体系一、Oracle后台进程概览1.1 DBWn(Database Writer Process)1.2 LGWR(Log Writer Process)1.3 SMON(System Monitor Process)1.4 PMON&#…

【大数据学习 | kafka高级部分】文件清除原理

2. 两种文件清除策略 kafka数据并不是为了做大量存储使用的,主要的功能是在流式计算中进行数据的流转,所以kafka中的数据并不做长期存储,默认存储时间为7天 那么问题来了,kafka中的数据是如何进行删除的呢? 在Kafka…

浏览器存储策略解析(三)Local/sessionStorage实战:如何查看本地浏览器上数据

物理意义上的localStorage/sessionStorage在哪里 我们都知道,localStorage存于本地,sessionStorage存于会话,这是见名知意可以得到的。但是在物理层面他们究竟存储在哪里呢? localStorage和sessionStorage一样,是存储…

设计模式讲解02—责任链模式(Chain)

1. 概述 定义:责任链模式是一种行为型模式,在这个模式中,通常创建了一个接收者对象的链来处理请求,该请求沿着链的顺序传递。直到有对象处理该请求为止,从而达到解耦请求发送者和请求处理者的目的。 解释:责…

判断二叉搜索树(递归)

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。binary search tree (BST) 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 …

私有化视频平台EasyCVR海康大华宇视视频平台视频诊断技术是如何实时监测视频质量的?

在现代视频监控系统中,确保视频流的质量和稳定性至关重要。随着技术的进步,视频诊断技术已经成为实时监测视频质量的关键工具。这种技术通过智能分析算法对视频流进行实时评估和处理,能够自动识别视频中的各种质量问题,并给出相应…

大语言模型(LLM)量化基础知识(一)

请大家关注我的知乎博客:- 派神 - - 知乎 随着大型语言模型 (LLM) 的参数数量的增长,与其支持硬件(加速器内存)增长速度之间的差距越来越大,如下图所示: 上图显示,从 2017 年到 2022 年,语言模…

【comfyui教程】ComfyUI 现已支持 Stable Diffusion 3.5 Medium!人人都能轻松上手的图像生成利器

前言 ComfyUI 现已支持 Stable Diffusion 3.5 Medium!人人都能轻松上手的图像生成利器 大家翘首以盼的Stable Diffusion 3.5 Medium模型终于来了!就在今天,Stability AI 正式推出了这款“亲民版”平衡模型,让创作者们得以在消费…

大模型微调技术 --> LoRA 系列之 AdaLoRA

AdaLoRA 1.摘要 之前的微调方法(如低秩更新)通常将增量更新的预算均匀地分布在所有预训练的权重矩阵上,并且忽略了不同权重参数的不同重要性。结果,微调结果不是最优的。 为了弥补这一差距,我们提出了AdaLoRA,它根据权重矩阵的…

带你搞懂红黑树的插入和删除

文章目录 1. 红黑树1.1 红黑树的概念1.2 红黑树的性质1.3 红黑树节点的定义1.4 红黑树的插入找到插入的位置调节平衡 1.5 红黑树的删除删除节点平衡调整 1.6 红黑树和AVL树的比较 1. 红黑树 1.1 红黑树的概念 红黑树也是一种二叉搜索树,但是在每一个节点上增加了一个存储位表…

揭秘全向轮运动学:机动艺术与上下位机通信的智慧桥梁

✨✨ Rqtz 个人主页 : 点击✨✨ 🌈Qt系列专栏:点击 🎈Qt智能车上位机专栏: 点击🎈 本篇文章介绍的是有关于全向轮运动学分析,单片机与上位机通信C代码以及ROS里程计解算的内容。 目录 大纲 ROS(机器人操作系统&…

移远通信推出八款天线新品,覆盖5G、4G、Wi-Fi和LoRa领域

近日,全球领先的物联网整体解决方案供应商移远通信宣布,再次推出八款高性能天线新品,进一步丰富其天线产品阵容,更好地满足全球客户对高品质天线的更多需求。具体包括5G超宽带天线YECT005W1A和YECT004W1A、5G天线YECT028W1A、4G天…

【设计模式系列】桥接模式(十三)

一、什么是桥接模式 桥接模式(Bridge Pattern)是一种结构型设计模式,其核心目的是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式主要用于处理那些在设计时无法确定实现细节的场合,或者需要在多个实现之间…

Java多态和继承(下篇)

今天接着学习多态和继承 目录 1 继承1.1 再谈初始化1.2 protect关键字1.3 继承方式1.4 final 关键字1.5 组合 2 多态2.1 多态的概念2.2 多态实现条件2.3 重写2.4 向上转型和向下转型2.4.1 向上转型2.4.2 向下转型 2.5 多态的优缺点2.6 避免在构造方法中使用重写的方法 总结 1 继…

动态规划理论基础和习题【力扣】【算法学习day.25】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非常非常高滴&am…

数据结构之顺序表(C语言)

1 线性表 线性表是n个具有相同特性的数据元素的有限序列,是一种在实际中广泛应用的数据结构,常见的线性表有:顺序表、链表、栈、队列、字符串等。 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是…

Qt——窗口

一.窗口概述 Qt 窗口是通过 QMainWindow 类来实现的。 QMainWindow是一个为用户提供主窗口程序的类,继承QWidget类,并且提供一个预定义的布局。包含一个菜单栏(menu bar),多个工具栏(tool bars&#xff0…