肯尼斯·里科《C和指针》第10章 结构和联合(2)结构、指针和成员

想吐槽的一点是如果我们当时上课也是这样讲就好了,,,

直接或通过指针访问结构和它们的成员的操作符是相当简单的,但是当它们应用于复杂的情形时就有可能引起混淆。这里有几个例子,能帮助大家更好地理解这两个操作符的工作过程。这些例子使用了下面的声明:

类型为EX的结构可以用下面的图表示。

这里用图的形式来表示结构,可使这些例子看上去更清楚一些。事实上,上图并不完全准确,因为编译器只要有可能,就会设法避免成员之间的浪费空间。

第一个例子将使用这些声明:

Ex        x = { 10, "Hi", { 5, { -1, 25 } }, 0 };
Ex        *px = &x;

它将产生下面这些变量:

访问指针

让我们从指针变量开始。表达式px的右值如下所示。

px是一个指针变量,但此处并不存在任何间接访问操作符,所以这个表达式的值就是px的内容。这个表达式的左值如下所示。

它显示了px的旧值将被一个新值所取代。

现在考虑表达式px+1。这个表达式并不是一个合法的左值,因为它的值并不存储于任何可标识的内存位置。这个表达式的右值更为有趣。如果px指向一个结构数组的元素,这个表达式将指向该数组的下一个结构。但就算如此,这个表达式仍然是非法的,因为我们没办法分辨内存下一个位置所存储的是这些结构元素之一还是其他东西。编译器无法检测到这类错误,所以必须自己判断指针运算是否有意义

访问结构

我们可以使用*操作符对指针执行间接访问。表达式*px的右值是px所指向的整个结构。

间接访问操作随箭头访问结构,所以使用实线显示,其结果就是整个结构。可以把这个表达式赋值给另一个类型相同的结构,也可以把它作为点操作符的左操作数,访问一个指定的成员。也可以把它作为参数传递给函数,还可以把它作为函数的返回值返回(不过,最后这两个操作需要考虑效率问题,以后将会对此详述)。表达式*px的左值如下所示。

这里,结构将接受一个新值,或者更精确地说,它将接受它的所有成员的新值。作为左值,重要的是位置,而不是这个位置所保存的值。

表达式*px+1是非法的,因为*px的结果是一个结构。C语言并没有定义结构和整型值之间的加法运算。但表达式*(px+1)又如何呢?如果x是一个数组的元素,这个表达式表示它后面的那个结构。但是,x是一个标量,所以这个表达式实际上是非法的。

访问结构成员

现在让我们来看一下箭头操作符。表达式px->a的右值如下所示。

->操作符对px执行间接访问操作(由实线箭头提示),它首先得到它所指向的结构,然后访问成员a。如果拥有一个指向结构的指针但又不知道结构的名字,便可以使用表达式px->a。如果知道这个结构的名字,也可以使用功能相同的表达式x.a。

在此我们稍作停顿,相互比较一下表达式*px和px->a。在这两个表达式中,px所保存的地址都用于寻找这个结构。但结构的第1个成员是a,所以a的地址和结构的地址是一样的。这样px看上去是指向整个结构,同时指向结构的第1个成员:毕竟,它们具有相同的地址。但是,这个分析只有一半是正确的。尽管两个地址的值是相等的,但它们的类型不同。变量px被声明为一个指向结构的指针,所以表达式*px的结果是整个结构,而不是它的第1个成员

访问嵌套的结构

为了访问本身也是结构的成员c,可以使用表达式px->c。它的左值是整个结构。

这个表达式可以使用点操作符访问c的特定成员。例如,表达式px->c.a具有下面的右值:

这个表达式既包含了点操作符,也包含了箭头操作符。之所以使用箭头操作符,是因为px并不是一个结构,而是一个指向结构的指针。接下来之所以要使用点操作符,是因为px->c的结果并不是一个指针,而是一个结构。

这里有一个更为复杂的表达式:

*px->c.b

如果对它进行逐步分析,这个表达式还是比较容易弄懂的。它有3个操作符,首先执行的是箭头操作符。px->c的结果是结构c。在表达式中增加.b来访问结构c的成员b。b是一个数组,所以px->b.c的结果是一个(常量)指针,它指向数组的第1个元素。最后对这个指针执行间接访问,所以表达式的最终结果是数组的第1个元素。这个表达式可以图解为如下形式。

访问指针成员

表达式px->d的结果如我们所料——它的右值是0,它的左值是它本身的内存位置。表达式*px->d更为有趣。这里间接访问操作符作用于成员d所存储的指针值。但d包含了一个NULL指针,所以它不指向任何东西。对一个NULL指针进行解引用操作是个错误,但正如以前讨论的那样,有些环境不会在运行时捕捉到这个错误。在这些机器上,程序将访问内存位置0的内容,把它也当作是结构成员之一,如果系统未发现错误,它还将继续下去。这个例子说明,对指针进行解引用操作之前检查一下它是否有效是非常重要的。

让我们创建另一个结构,并把x.d设置为指向它:

Ex        y;
x.d = &y;

现在可以对表达式*px->d求值。

成员d指向一个结构,所以对它执行间接访问操作的结果是整个结构。这个新的结构并没有显式地初始化,所以在图中并没有显示它的成员的值。

正如我们可能预料的那样,这个新结构的成员可以通过在表达式中增加更多的操作符进行访问。我们使用箭头操作符,因为d是一个指向结构的指针。下面这些表达式是执行什么任务的呢?

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

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

相关文章

单片机串口 奇偶校验 配置问题

一、问题描述 使用GD32单片机串口进行通信测试,单片机的串口配置的是偶校验(Even)、数据位为8、停止位为1、波特率为9600。串口测试软件用的格西烽火,软件的配置如下:   单片机通过串口和串口测试软件进行通信交互,软件收到的数…

基于深度学习算法的轴承故障自主分类

1. 要求 轴承有3种故障:外圈故障,内圈故障,滚珠故障,外加正常的工作状态。如表1所示,结合轴承的3种直径(直径1,直径2,直径3),轴承的工作状态有10类: 表1 轴承故障类别 外…

netty-websocket扩展协议及token鉴权补充

文章源码:gitee 源码部分可以看上一篇文章中的源码分析netty-websocket 鉴权token及统一请求和响应头(鉴权控制器) 最近刚好没事,看到有朋友说自定义协议好搞,我就想了想,发现上面那种方式实现确实麻烦&…

CentOS 8 安装配置 Hadoop3.3.6 伪分布式安装方式(适用于开发和调试)

1.配置服务器ssh免密登录,否则后面启动会报错:尝试通过SSH连接到主机出现认证错误的提示 配置服务器ssh免密登录: 1.生成SSH密钥对(如果尚未生成): 执行下面的命令生成密钥对,一直回车即可 ssh…

转融通业务是什么?好处和弊端是什么?

转融通业务是指证券金融公司借入证券、筹得资金后,再转借给证券公司,为证券公司开展融资融券业务提供资金和证券来源,包括转融券业务和转融资业务两部分。从证券金融公司角度看,向证券公司提供资金和证券供其开展融资融券业务&…

大型语言模型(LLM)的优势、劣势和风险

最近关于大型语言模型的奇迹()已经说了很多LLMs。这些荣誉大多是当之无愧的。让 ChatGPT 描述广义相对论,你会得到一个非常好(且准确)的答案。然而,归根结底,ChatGPT 仍然是一个盲目执行其指令集…

YOLO-World——超级轻量级开放词汇目标检测方法

前言 目标检测一直是计算机视觉领域中不可忽视的基础挑战,对图像理解、机器人技术和自主驾驶等领域具有广泛应用。随着深度神经网络的发展,目标检测方面的研究取得了显著进展。尽管这些方法取得了成功,但它们存在一些限制,主要体…

Linux嵌入式开发+驱动开发-中断

swi汇编指令可以产生软中断,以下是硬件中断的产生到执行完毕的全过程: 在自己设计的芯片“CPU响应中断”程序的第四个步骤可以转向“中断向量控制器”,中断向量控制器中存储中断元服务地址即处理中断处理程序的地址,而不用使用0X1…

arm 汇编积累

C语言函数与汇编对应关系 一、MOV 系列指令 1、指令格式 MOV{条件}{S} 目的寄存器,源操作数 2、含义解析: (1):mov 指令传送数据 案例: MOV R0,R1 ; R0 R1; MOV PC,R14 ;PC R14; MOV R0,R…

c#cad 创建-圆(二)

运行环境 vs2022 c# cad2016 调试成功 一、代码说明 这段代码是一个AutoCAD插件,用于在模型空间中创建一个圆形。 首先,我们需要定义一个命令类CreateCircleCommand,并在命名空间CreateCircleInCad中声明。 在CreateCircleCommand类中&a…

探索设计模式的魅力:外观模式简化术-隐藏复杂性,提供简洁接口的设计秘密

设计模式专栏:http://t.csdnimg.cn/U54zu 目录 引言:探索简化之路 一、起源和演变 二、场景案例分析 2.1 不用模式实现:用一坨坨代码实现 2.2 问题 2.3 外观模式重构代码 定义 界面 接口 利用外观模式解决问题步骤 外观模式结构和说明 重构…

【计算机网络基础篇】学习笔记系列之二《游览器输入URL后发生了什么?》

文章目录 1,问题提出2,输入URL过程用到的协议3,输入URL过程分析3.1,孤单小弟 - HTTP3.2,真实地址查询 - DNS3.2,指南好帮手 - 协议栈3.3,可靠传输 - TCP3.4,远程定位- IP3.5&#xf…