肯尼斯·里科《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.mfbz.cn/a/374258.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Three.js学习6:透视相机和正交相机

一、相机 相机 camera,可以理解为摄像机。在拍影视剧的时候,最终用户看到的画面都是相机拍出来的内容。 Three.js 里,相机 camera 里的内容就是用户能看到的内容。从这个角度来看,相机其实就是用户的视野,就像用户的眼…

Sentinel(理论版)

Sentinel 1.什么是Sentinel Sentinel 是一个开源的流量控制组件,它主要用于在分布式系统中实现稳定性与可靠性,如流量控制、熔断降级、系统负载保护等功能。简单来说,Sentinel 就像是一个交通警察,它可以根据系统的实时流量&…

电力负荷预测 | 基于TCN的电力负荷预测(Python)———模型构建

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 基于TCN的电力负荷预测(Python) python3.8 keras2.6.0 matplotlib3.5.2 numpy1.19.4 pandas1.4.3 tensorflow==2.6.0

停止内耗,做有用的事

很多读者朋友跟我交流的时候,都以为我有存稿,于是听到我说每周四现写的时候都很惊讶。其实没什么好惊讶的,每周四我都会把自己关在书房里一整天,断掉一切电话、微信、邮件,从中午写到晚上,直到写完为止。 这…

力扣● 62.不同路径 ● 63. 不同路径 II

● 62.不同路径 单解这道题的话,发现第一行或者第一列的这些位置,都只有一条路径走到,所以路径条数都是1。这就是初始化。坐标大于第一行第一列的这些位置,因为机器人只能向下/向右走,所以只能从上个位置向下走和从左…

用友U8 Cloud ReportDetailDataQuery SQL注入漏洞复现(QVD-2023-47860)

0x01 产品简介 用友U8 Cloud 提供企业级云ERP整体解决方案,全面支持多组织业务协同,实现企业互联网资源连接。 U8 Cloud 亦是亚太地区成长型企业最广泛采用的云解决方案。 0x02 漏洞概述 用友U8 cloud ReportDetailDataQuery 接口处存在SQL注入漏洞,攻击者未经授权可以访…

【Docker】了解Docker Desktop桌面应用程序,TA是如何管理和运行Docker容器(2)

欢迎来到《小5讲堂》,大家好,我是全栈小5。 这是《Docker容器》系列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对…

redis源码之:集群创建与节点通信(2)

在上一篇redis源码之:集群创建与节点通信(1)我们可知,在集群中,cluster节点之间,通过meet将对方加入到本方的cluster->nodes列表中,并在后续过程中,不断通过clusterSendPing发送p…

2 月 5 日算法练习- 动态规划

DP&#xff08;动态规划&#xff09;全称Dynamic Programming&#xff0c;是运筹学的一个分支&#xff0c;是一种将复杂问题分解成很多重叠的子问题、并通过子问题的解得到整个问题的解的算法。 在动态规划中有一些概念&#xff1a; n<1e3 [][] &#xff0c;n<100 [][][…

文心一言4.0API接入指南

概述 文心一言是百度打造出来的人工智能大语言模型&#xff0c;具备跨模态、跨语言的深度语义理解与生成能力&#xff0c;文心一言有五大能力&#xff0c;文学创作、商业文案创作、数理逻辑推算、中文理解、多模态生成&#xff0c;其在搜索问答、内容创作生成、智能办公等众多…

租游戏服务器多少钱1个月?一年价格多少?

游戏服务器租用多少钱一年&#xff1f;1个月游戏服务器费用多少&#xff1f;阿里云游戏服务器26元1个月、腾讯云游戏服务器32元&#xff0c;游戏服务器配置从4核16G、4核32G、8核32G、16核64G等配置可选&#xff0c;可以选择轻量应用服务器和云服务器&#xff0c;阿腾云atengyu…

42、WEB攻防——通用漏洞文件包含LFIRFI伪协议编码算法代码审计

文章目录 文件包含文件包含原理攻击思路文件包含分类 sessionPHP伪协议进行文件包含 文件包含 文件包含原理 文件包含其实就是引用&#xff0c;相当于C语言中的include <stdio.h>。文件包含漏洞常出现于php脚本中&#xff0c;当include($file)中的$file变量用户可控&am…

Oracle笔记-为表空间新增磁盘(ORA-01691)

如下报错&#xff1a; 原因是Oracle表空间满了&#xff0c;最好是新增一个存储盘。 #查XXX命名空间目前占用了多大的空间 select FILE_NAME,BYTES/1024/1024 from dba_data_files where tablespace_name XXXX #这里的FILE_NAME能查到DBF的存储位置#将对应的datafile设置为30g…

C++中的析构函数

一、析构函数概念 析构函数不是完成对象的销毁&#xff0c;对象的销毁是由编译器完成的。析构函数完成的是对象中资源的清理工作。通常是对对象中动态开辟的空间进行清理。 二、析构函数特性 1.析构函数的函数名是 ~类名 2.析构函数无参数无返回值 3.一个类中只能有一个析…

如何让 Pages 文字分为两栏或更多栏?

通常一份文件都是由上往下仅有「一栏」而已&#xff0c;但在某些情况的排版&#xff0c;我们需要两栏甚至三栏的设计&#xff0c;在Pages 要如何做到呢&#xff1f;来看看吧。 将 Pages 文件改为双栏式设计 点一下「格式」>「布局」&#xff0c;就可以看到预设的「直栏」数…

很容易感到疲惫,怎么办?

最近&#xff0c;经常听到一些朋友诉苦&#xff0c;说&#xff1a;总觉得每天下来都特别累&#xff0c;也没干什么&#xff0c;就觉得无精打采&#xff0c;没有动力&#xff0c;提不起劲&#xff0c;什么都不想干…… 这种疲惫不是身体层面的&#xff0c;而是精神层面的。身体不…

外汇天眼:外汇天眼:注意,19个外汇平台因诈骗被监管拉黑!

近年来&#xff0c;全球金融市场出现了众多非法投资平台&#xff0c;这些平台利用虚假宣传和高回报承诺欺骗投资者&#xff0c;造成了严重的经济损失。为了保护投资者利益&#xff0c;监管机构也在加大力度打击这些非法平台。就在最近&#xff0c;又有19个外汇交易平台因涉嫌诈…

redis下载与安装教程(centos下)

文章目录 一&#xff0c;redis下载1.1上传到linux服务器上 二&#xff0c;redis安装2.1 安装依赖2.2 解压包2.3 编译并安装2.4 指定配置启动2.5 设置redis开机自启 一&#xff0c;redis下载 官网&#xff1a; https://redis.io1.1上传到linux服务器上 我用filezila上传到/us…

【AWS】step-functions服务编排

文章目录 step-functionsState machine typeStandard workflowsExpress workflows design skillsError handlingsaga Transaction processing控制分布式系统中的并发性 收费 作为AWS Serverless无服务器的一个重要一环 使用step-functions方法将 AWS 服务链接在一起 step-funct…

跟着cherno手搓游戏引擎【22】CameraController

前置&#xff1a; YOTO.h: #pragma once//用于YOTO APP#include "YOTO/Application.h" #include"YOTO/Layer.h" #include "YOTO/Log.h"#include"YOTO/Core/Timestep.h"#include"YOTO/Input.h" #include"YOTO/KeyCod…
最新文章