肯尼斯·里科《C和指针》第6章 指针(4)实例
肯尼斯·里科《C和指针》第6章 指针(1)-CSDN博客
肯尼斯·里科《C和指针》第6章 指针(2)-CSDN博客
肯尼斯·里科《C和指针》第6章 指针(3)-CSDN博客
6.12 实例
/*
** 计算一个字符串的长度。
*/
#include <stdlib.h>
size_t
strlen( char *string )
{int length = 0;/*** 依次访问字符串的内容,计数字符数,直到遇见NUL终止符。*/while( *string++ != '\0' )length += 1;return length;
}
在指针到达字符串末尾的NUL字节之前,while语句中*string++表达式的值一直为真。它同时增加指针的值,用于下一次测试。这个表达式甚至可以正确地处理空字符串。
如果这个函数调用时传递给它的是一个NULL指针,那么while语句中的间接访问将会失败。函数是不是应该在解引用指针前检查这个条件?从绝对安全的角度讲,应该如此。但是,这个函数并不负责创建字符串。如果它发现参数为NULL,它肯定发现了一个出现在程序其他地方的错误。当指针创建时检查它是否有效是合乎逻辑的,因为这样只需检查一次。这个函数采用的就是这种方法。如果函数失败是因为粗心大意的调用者懒得检查参数的有效性而引起的,那是他活该如此。
程序6.2和程序6.3增加了一层间接访问。它们在一些字符串中搜索某个特定的字符值,但我们使用指针数组来表示这些字符串,如图6.1所示。函数的参数是strings和value,strings是一个指向指针数组的指针,value是我们所查找的字符值。注意,指针数组以一个NULL指针结束。函数将检查这个值以判断循环何时结束。下面这行表达式
while( ( string = *strings++ ) != NULL ) {完成3项任务:把strings当前所指向的指针复制到变量string中;增加strings的值,使它指向下一个值;测试string是否为NULL。当string指向当前字符串中作为终止标志的NUL字节时,内层的while循环就终止。
程序6.2 在一组字符串中查找:版本1 s_srch1.c
/* ** 给定一个指向以NULL结尾的指针列表的指针,在列表中的字符串中查找一个特定的字符。 */ #include <stdio.h> #define TRUE 1 #define FALSE 0 int find_char( char **strings, char value ) {char*string; /* 我们当前正在查找的字符串 *//*** 对于列表中的每个字符串 ...*/while( ( string = *strings++ ) != NULL ){/*** 观察字符串中的每个字符,看看它是不是我们需要查找的那个。*/while( *string != '\0' ){if( *string++ == value )return TRUE;}}return FALSE; }if( *string++ == value )如果string尚未到达其结尾的NUL字节,就执行上面这条语句,它测试当前的字符是否与需要查找的字符匹配,然后增加指针的值,使它指向下一个字符。
后增加指针的值,使它指向下一个字符。程序6.3实现相同的功能,但它不需要对指向每个字符串的指针进行复制。但是,由于存在副作用,这个程序将破坏这个指针数组。这个副作用使该函数不如前面那个版本有用,因为它只适用于字符串只需要查找一次的情况。
程序6.3 在一组字符串中查找:版本2 s_srch2.c
/* ** 给定一个指向以NULL结尾的指针列表的指针,在列表中的字符串中查找一个特定的字符。这个函数将破坏这些指针,所以它只适用于这组字符串只使用一次的情况。 */ #include <stdio.h> #include <assert.h> #define TRUE 1 #define FALSE 0 int find_char( char **strings, int value ) {assert( strings != NULL );/*** 对于列表中的每个字符串 ...*/while( *strings != NULL ){/*** 观察字符串中的每个字符,看看它是否是我们查找的那个。*/while( **strings != '\0' ){if( *(*strings)++ == value )return TRUE;}strings++;}return FALSE; }但是,在程序6.3中存在两个有趣的表达式。第1个是**strings。第1个间接访问操作访问指针数组中的当前指针,第2个间接访问操作随该指针访问字符串中的当前字符。内层的while语句测试这个字符的值并观察是否到达了字符串的末尾。
第2个有趣的表达式是*(*strings)++。这里需要括号,这样才能使表达式以正确的顺序进行求值。第1个间接访问操作访问列表中的当前指针。增值操作把该指针所指向的那个位置的值加1,但第2个间接访问操作作用于原先那个值的副本。这个表达式的直接作用是对当前字符串中的当前字符进行测试,看看是否到达了字符串的末尾。它的副作用是指向当前字符串字符的指针值将增加1。
6.13 指针的运算
实际的过程
指针加上一个整数的结果是另一个指针。问题是,它指向哪里?如果将一个字符指针加1,运算结果产生的指针指向内存中的下一个字符。float占据的内存空间不止1字节,如果将一个指向float的指针加1,将会发生什么呢?它会不会指向该float值内部的某个字节呢?
幸运的是,答案是否定的。当一个指针和一个整数量执行算术运算时,整数在执行加法运算前始终会根据合适的大小进行调整。这个“合适的大小”就是指针所指向类型的大小,“调整”就是把整数值和“合适的大小”相乘。为了更好地说明,试想在某台机器上,float占据4字节。在计算float型指针加3的表达式时,这个3将根据float类型的大小(此例中为4)进行调整(相乘)。这样,实际加到指针上的整型值为12。
把3与指针相加使指针的值增加3个float的大小,而不是3字节。这个行为较之获得一个指向一个float值内部某个位置的指针更为合理。表6.5包含了一些加法运算的例子。调整的美感在于指针算法并不依赖于指针的类型。换句话说,如果p是一个指向char的指针,那么表达式p+1就指向下一个char。如果p是个指向float的指针,那么p+1就指向下一个float,其他类型也是如此。
表6.5 指针运算结果
算数运算
C的指针算术运算只限于两种形式。
第1种形式是:指针±整数
标准定义这种形式只能用于指向数组中某个元素的指针,如下图所示。
第2种类型的指针运算具有如下形式:指针-指针
只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针,如下所示。
两个指针相减的结果的类型是ptrdiff_t,这是一种有符号整数类型。减法运算的值是两个指针在内存中的距离(以数组元素的长度为单位,而不是以字节为单位),因为减法运算的结果将除以数组元素类型的长度。例如,如果p1指向array[i]而p2指向array[j],那么p2-p1的值就是j-i的值。
让我们看一下它是如何作用于某个特定类型的。假定上图中数组元素的类型为float,每个元素占据4字节的内存空间。如果数组的起始位置为1000,p1的值是1004,p2的值是1024,但表达式p2-p1的结果值将是5,因为两个指针的差值(20)将除以每个元素的长度(4)。
同样,这种对差值的调整使指针的运算结果与数据的类型无关。不论数组包含的元素类型如何,这个指针减法运算的值总是5。
那么,表达式p1-p2是否合法呢?是的,如果两个指针都指向同一个数组中的元素,这个表达式就是合法的。在前一个例子中,这个值将是-5。
如果两个指针所指向的不是同一个数组中的元素,那么它们之间相减的结果是未定义的。就像如果你把两个位于不同街道的房子的门牌号码相减,不可能获得这两所房子间的房子数一样。程序员无从知道两个数组在内存中的相对位置,如果不知道这一点,两个指针之间的距离就毫无意义。
关系运算
对指针执行关系运算也是有限制的。可以用下列关系操作符对两个指针值进行比较:
< <= > >=不过前提是它们都指向同一个数组中的元素。根据所使用的操作符,比较表达式将告诉你哪个指针指向数组中更前或更后的元素。标准并未定义如果两个任意的指针进行比较时会产生什么结果。
不过,可以在两个任意的指针间执行相等或不相等测试,因为这类比较的结果和编译器选择在何处存储数据并无关系——指针要么指向同一个地址,要么指向不同的地址。
让我们再观察一个循环,它用于清除一个数组中的所有元素。
for语句使用了一个关系测试来决定是否结束循环。这个测试是合法的,因为vp和指针常量都指向同一数组中的元素(事实上,这个指针常量所指向的是数组最后一个元素后面的那个内存位置,虽然在最后一次比较时,vp也指向了这个位置,但由于此时未对vp执行间接访问操作,因此它是安全的)。使用!=操作符代替<操作符也是可行的,因为如果vp未到达它的最后一个值,这个表达式的结果将总是假的。
相关文章:
肯尼斯·里科《C和指针》第6章 指针(4)实例
肯尼斯里科《C和指针》第6章 指针(1)-CSDN博客 肯尼斯里科《C和指针》第6章 指针(2)-CSDN博客 肯尼斯里科《C和指针》第6章 指针(3)-CSDN博客 6.12 实例 /* ** 计算一个字符串的长度。 */ #include <…...
diffusers flask streamlit 简洁可视化文生图页面
参考: https://python-bloggers.com/2022/12/stable-diffusion-application-with-streamlit/ https://github.com/LowinLi/stable-diffusion-streamlit 项目结构 本项目很简洁,暂时每次只能返回一张图片;gpu资源T4 16g;测试下来基本也只能支持同时一个人使用 flask:作为…...
ubuntu 使用VNC链接树莓派
ubuntu PC端安装remina sudo apt-add-repository ppa:remmina-ppa-team/remmina-next 然后,运行以下命令来安装 Remmina 软件包: sudo apt update sudo apt install remmina remmina-plugin-rdp remmina-plugin-secret flatpak run -- pkill remmina p…...
水利部:加大北斗、无人机等安全监测新技术的应用推广
水利部:加大北斗、无人机等安全监测新技术的应用推广 近日,水利部召开2023年水库安全管理情况新闻发布会。会上,副部长刘伟平介绍有关情况,并与水利工程建设司、运行管理司、水旱灾害防御司负责人回答记者提问。 为了高质量…...
如何定位和优化程序CPU、内存等性能之巅
摘要 性能优化指在不影响系统运行正确性的前提下,使之运行得更快,完成特定功能所需的时间更短,或拥有更强大的服务能力。本文将介绍性能优化的基本概念以及如何定位和优化程序中的CPU、内存和IO瓶颈。 引言 随着计算机系统的日益复杂和应用…...
一体机旅游景区污水处理设备工艺说明
一体机旅游景区污水处理设备工艺说明 原水浓度:COD≤500mg/L,BOD≤300mg/L,NH3-N≤40mg/L,超过以上浓度需另行设计。 出水标准:COD≤60mg/L,BOD≤20mg/L,NH3-N≤15mg/L,出水要求如更…...
java返回文件时为图片或pdf等设置在线预览或下载
设置Content-Disposition响应头类型 "inline"查看预览 ; "attachment"下载; inline:表示回复中的消息体会以页面的一部分或者整个页面的形式展示 attchment:以附件形式被下载到本地;/*** 文件或图…...
微信公众号对接--客服消息
当你关注公众号,然后在公众号里面发送消息,会收到回复,这个就是客服消息 参考文档:接收普通消息 接收事件推送 客服接口-发消息 想要对接客服消息,首先要获取access_token,这个可以参考我之前的文章:对接微信公众号-CSDN博客 回…...
花几分钟整点jmeter花活,轻松超越90%软件测试
jmeter 可以做性能测试,这个很多人都知道,那你知道,jmeter 可以在启动运行时,指定线程数和运行时间,自定义性能场景吗? jmeter 性能测试,动态设定性能场景 平时,我们使用 jmeter 进…...
类脑研究之脑组成及神经系统相关理论!大脑是什么?大脑和脑有什么区别?大脑皮层和脑膜什么关系?人的神经系统有哪些?
目录 1 引言2 神经系统3 脑组成3.1 大脑成分3.2 大脑外部:脑膜3.3 大脑中部:大脑皮层3.4 大脑内部3.5 脑干3.6 小脑 1 引言 为了深入研究类脑,必须了解大脑的结构和机制。从神经系统分级和脑组成两个角度出发,详细介绍了大脑的生…...
【Vue按键修饰符详细介绍】
Vue按键修饰符详细介绍 1. 按键修饰符2. 实现原理3. 使用方法4. 常用的按键修饰符5. 自定义按键修饰符6. 系统修饰键7. 事件修饰符的链式使用8. .exact 修饰符 1. 按键修饰符 Vue.js 中的按键修饰符使得键盘事件处理变得十分简单,它们通常与 v-on 指令(…...
url 地址中的敏感信息脱敏处理
url 跳转时,系统自动加密解密处理,适用于调用方不适合加密处理的情况 // 定义一个名为encodeURIUrlParams的函数 encodeURIUrlParams() { // 创建一个URLSearchParams对象,该对象用于处理URL的查询字符串部分 const urlParams new URLS…...
慢速 HTTP 攻击 Slow HTTP Attack
漏洞名称 :Slow Http attack、慢速攻击 漏洞描述:慢速攻击基于HTTP协议,通过精心的设计和构造,这种特殊的请求包会造成服务器延时,而当服务器负载能力消耗过大即会导致拒绝服务。HTTP协议规定,HTTP Reques…...
2024年“计算机视觉处理设计开发工程师”最后几天报考中!
为进一步贯彻落实中共中央印发《关于深化人才发展体制机制改革的意见》和国务院印发《关于“十四五”数字经济发展规划》等有关工作的部署要求,深入实施人才强国战略和创新驱动发展战略,加强全国数字化人才队伍建设,持续推进人工智能专业人员…...
基于ssm的教务信息平台的设计与实现+jsp论文
摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统教务信息管理难度大,容错率低,管理…...
哪种护眼灯对眼睛好?五款高品质考研台灯推荐
眼睛是我们感知世界的窗户,眼睛对光的敏感度非常高。长时间接触强光或不适宜的光线环境可能会对眼睛造成伤害。因此,选择一款适合自己的护眼台灯非常重要。护眼台灯能够模拟自然光的光谱,减少眼睛对不良光线的伤害。它具备调节光线亮度&#…...
安防视频云平台/可视化监控云平台ARM版EasyCVR无法下载录像文件,如何解决?
视频集中存储/云存储/视频监控管理平台EasyCVR能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频资源的鉴权管理、按需调阅、全网分发、智能分析等。GB28181视频监控/AI智能大数据视频分析EasyCVR平台已经广泛应用在工地…...
如何用Docker部署Nacos服务并结合内网穿透实现公网访问管理界面?
文章目录 1. Docker 运行Nacos2. 本地访问Nacos3. Linux安装Cpolar4. 配置Nacos UI界面公网地址5. 远程访问 Nacos UI界面6. 固定Nacos UI界面公网地址7. 固定地址访问Plik Nacos是阿里开放的一款中间件,也是一款服务注册中心,它主要提供三种功能:持久化…...
Logback框架基本认识
文章目录 一.什么是Logback1.1 初识Logbcak 二.Logbcak的结构三.日志的级别四.配置组件详解4.1 logger 日志记录器属性的介绍如何在配置文件里配置 4.2 appender 附加器 配合日志记录器的输出格式4.2.1 控制台附加器4.2.2 文件附加器4.3.3滚动文件附加器 4.3 Filter: 过滤器&am…...
移动安全-certutil
1 需求 需求1:获取应用文件的MD5 CertUtil -hashfile 文件路径 MD5 2 语法 C:\>certutil -?动词:-dump -- 转储配置信息或文件-dumpPFX -- 转储 PFX 结构-asn -- 分析 ASN.1 文件-decodehex -- 解码十六进制编码的…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...
Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...
麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...
CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx
“Reactive Stream Processing in Industrial IoT using DDS and Rx” 是指在工业物联网(IIoT)场景中,结合 DDS(Data Distribution Service) 和 Rx(Reactive Extensions) 技术,实现 …...




