(delphi11最新学习资料) Object Pascal 学习笔记---第6章第3节(字符串的内部结构 )

6.3.7 字符串的内部结构

一般情况下虽然使用字符串不需要了解其太多内部结构,但适当了解一下这种数据类型背后的实际数据结构还是很有趣的。在早期的 Pascal 语言中,字符串最多有 255 个元素,每个字符一个字节,第一个字节(或零字节)用于存储长度。从早期到现在已经过去了很长时间,但将字符串的一些额外信息作为其数据的一部分来存储的概念仍然是 Object Pascal 语言所采用的方法(与许多源自 C 语言并使用字符串结束符概念的语言不同)。

注解:ShortString 是传统 Pascal 字符串类型的名称,它是一个由一个byte字符或一个AnsiChar 字符组成的字符串,长度限制为 255 个字符。在桌面编译器中仍可使用 ShortString 类型,但在移动编译器中则不可用。您可以使用byte动态数组或 TBytes 表示类似的数据结构,也可以使用普通的Byte元素静态数组表示类似的数据结构。

如前所述,字符串变量只是指向堆上分配的数据结构的指针。实际上,存储在字符串中的值并不是对数据结构开头的引用,而是对字符串第一个字符的引用,字符串的元数据数值可从该位置的负偏移量获得。字符串类型数据的内存表示如下:

-12-10-8-4String引用地址
编码页元素大小引用计数长度第一个字符
-12 -10 -8 -4 字符串引用地址 代码页 元素大小 引用计数 长度 字符串的第一个字符

​ 第一个元素(从字符串本身开始倒数)是定义字符串长度的整数,第二个元素是引用计数。其他字段(用于桌面编译器)是以字节为单位的元素大小(1 或 2 字节),以及基于 ANSI 的旧字符串类型的编码页。

​ 令人惊讶的是,除了显而易见的长度函数外,大多数字段都可以通过特定的底层字符串元数据函数来访问:

function StringElementSize(const S: string): Word;
function StringCodePage(const S: string): Word;
function StringRefCount(const S: string): LongInt;

​ 例如,您可以创建一个字符串并查询其相关信息,就像我在StringMetaTest示例中所做的那样:

var
   Str1: string;
begin
   Str1 := 'F' + string.Create('o', 2);
   Show('SizeOf: ' + SizeOf(Str1).ToString);
   Show('Length: ' + Str1.Length.ToString);
   Show('StringElementSize: ' + StringElementSize(Str1).ToString);
   Show('StringRefCount: ' + StringRefCount(Str1).ToString);
   Show('StringCodePage: ' + StringCodePage(Str1).ToString);
   if StringCodePage(Str1) = DefaultUnicodeCodePage then
       Show('Is Unicode');
   Show('Size in bytes: ' + (Length(Str1) * StringElementSize(Str1)).ToString);
   Show('ByteLength: ' + ByteLength(Str1).ToString);

注解:程序动态构建 "Foo "字符串而不是固定为常量有一个特殊原因,那就是常量字符串的引用计数被禁用(或设置为-1)。在演示中,我倾向于为引用计数显示一个适当的值,因此采用了动态字符串结构。

该程序产生类似以下的输出:

SizeOf: 4
Length: 3
StringElementSize: 2
StringRefCount: 1
StringCodePage: 1200
Is Unicode
Size in bytes: 6
ByteLength: 6

​ UnicodeString类型变量返回的编码页是1200,这个数字存储在全局变量 DefaultUnicodeCodePage 中。在上面的代码(及其输出)中,你可以清楚地看到字符串变量的大小(一律为 4)、逻辑长度和物理长度(以字节为单位)之间的差异。

​ 将每个字符的字节数乘以字符数,或者调用 ByteLength,就可以得到逻辑长度。不过,该函数不支持旧版桌面编译器的某些字符串类型。#### 6.3.7 字符串的内部结构

一般情况下虽然使用字符串不需要了解其太多内部结构,但适当了解一下这种数据类型背后的实际数据结构还是很有趣的。在早期的 Pascal 语言中,字符串最多有 255 个元素,每个字符一个字节,第一个字节(或零字节)用于存储长度。从早期到现在已经过去了很长时间,但将字符串的一些额外信息作为其数据的一部分来存储的概念仍然是 Object Pascal 语言所采用的方法(与许多源自 C 语言并使用字符串结束符概念的语言不同)。

注解:ShortString 是传统 Pascal 字符串类型的名称,它是一个由一个byte字符或一个AnsiChar 字符组成的字符串,长度限制为 255 个字符。在桌面编译器中仍可使用 ShortString 类型,但在移动编译器中则不可用。您可以使用byte动态数组或 TBytes 表示类似的数据结构,也可以使用普通的Byte元素静态数组表示类似的数据结构。

如前所述,字符串变量只是指向堆上分配的数据结构的指针。实际上,存储在字符串中的值并不是对数据结构开头的引用,而是对字符串第一个字符的引用,字符串的元数据数值可从该位置的负偏移量获得。字符串类型数据的内存表示如下:

-12-10-8-4String引用地址
编码页元素大小引用计数长度第一个字符
-12 -10 -8 -4 字符串引用地址 代码页 元素大小 引用计数 长度 字符串的第一个字符

​ 第一个元素(从字符串本身开始倒数)是定义字符串长度的整数,第二个元素是引用计数。其他字段(用于桌面编译器)是以字节为单位的元素大小(1 或 2 字节),以及基于 ANSI 的旧字符串类型的编码页。

​ 令人惊讶的是,除了显而易见的长度函数外,大多数字段都可以通过特定的底层字符串元数据函数来访问:

function StringElementSize(const S: string): Word;
function StringCodePage(const S: string): Word;
function StringRefCount(const S: string): LongInt;

​ 例如,您可以创建一个字符串并查询其相关信息,就像我在StringMetaTest示例中所做的那样:

var
   Str1: string;
begin
   Str1 := 'F' + string.Create('o', 2);
   Show('SizeOf: ' + SizeOf(Str1).ToString);
   Show('Length: ' + Str1.Length.ToString);
   Show('StringElementSize: ' + StringElementSize(Str1).ToString);
   Show('StringRefCount: ' + StringRefCount(Str1).ToString);
   Show('StringCodePage: ' + StringCodePage(Str1).ToString);
   if StringCodePage(Str1) = DefaultUnicodeCodePage then
       Show('Is Unicode');
   Show('Size in bytes: ' + (Length(Str1) * StringElementSize(Str1)).ToString);
   Show('ByteLength: ' + ByteLength(Str1).ToString);

注解:程序动态构建 "Foo "字符串而不是固定为常量有一个特殊原因,那就是常量字符串的引用计数被禁用(或设置为-1)。在演示中,我倾向于为引用计数显示一个适当的值,因此采用了动态字符串结构。

该程序产生类似以下的输出:

SizeOf: 4
Length: 3
StringElementSize: 2
StringRefCount: 1
StringCodePage: 1200
Is Unicode
Size in bytes: 6
ByteLength: 6

​ UnicodeString类型变量返回的编码页是1200,这个数字存储在全局变量 DefaultUnicodeCodePage 中。在上面的代码(及其输出)中,你可以清楚地看到字符串变量的大小(一律为 4)、逻辑长度和物理长度(以字节为单位)之间的差异。

​ 将每个字符的字节数乘以字符数,或者调用 ByteLength,就可以得到逻辑长度。不过,该函数不支持旧版桌面编译器的某些字符串类型。

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

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

相关文章

使用 Docker 部署 Stirling-PDF 多功能 PDF 工具

1)Stirling-PDF 介绍 大家应该都有过这样的经历,面对一堆 PDF 文档,或者需要合并几个 PDF,或者需要将一份 PDF 文件拆分,又或者需要调整 PDF 中的页面顺序,找到的线上工具 要么广告满天飞,要么 …

OpenCV与机器学习:OpenCV实现主成分分析

OpenCV实现主成分分析 前言主成分分析(PCA)数据生成画图cv2.PCACompute绘制主成分分析结果 前言 维数灾难是指出现一定数量的特征(或者维度)后,分类器的性能将开始下降。特征越多,数据集中的信息就越多。但…

当前爆火的:ChatGPT4、Claude3、Gemini、Sora、GPTs及AI领域中的集中大模型的最新技术

原文链接:当前爆火的:ChatGPT4、Claude3、Gemini、Sora、GPTs及AI领域中的集中大模型的最新技术 第一:2024年AI领域最新技术 1.最新超强模型Claude3使用 2.OpenAI新模型-GPT-5 3.谷歌新模型-Gemini使用 4.Meta新模型-LLama3 5.阿里巴巴…

[C语言]——C语言常见概念(1)

目录 一.C语言是什么、 二.C语言的历史和辉煌 三.编译器的选择(VS2022为例) 1.编译和链接 2.编译器的对比 3.VS2022 的优缺点 四.VS项目和源文件、头文件介绍 五.第⼀个C语言程序 ​​​​​​​ 一.C语言是什么、 ⼈和⼈交流使⽤的是⾃然语⾔&…

时间序列-AR MA ARIMA

一、AR模型(自回归) AR探索趋势和周期性 预测依赖于过去的观测值和模型中的参数。模型的阶数 p pp 决定了需要考虑多少个过去时间点的观测值。 求AR模型的阶数 p和参数 ϕ i \phi_i ϕi​ ,常常会使用统计方法如最小二乘法、信息准则(如AIC、BIC&#xf…

15:Zookeeper高可用集群|分布式消息队列Kafka|搭建高可用Hadoop集群

Zookeeper高可用集群|分布式消息队列Kafka|搭建高可用Hadoop集群 Zookeeper集群Zookeeper角色与特性Zookeeper角色与选举Zookeeper的高可用Zookeeper可伸缩扩展性原理与设计Zookeeper安装zookeeper集群管理 Kafka概述在node节点上搭建3台kafka 高可用Had…

EdgeX Foundry - 导出数据到 MQTT 服务

文章目录 一、概述1.安装说明2.安装 EMQX3.MQTTX 工具 二、安装部署1.docker-comepse2.修改配置3.启动 EdgeX Foundry4.访问 UI4.1. consul4.2. EdgeX Console 5.测试 EdgeX Foundry # EdgeX Foundryhttps://iothub.org.cn/docs/edgex/ https://iothub.org.cn/docs/edgex/devi…

数字化时代下的内部审计转型方法与步骤

内部审计是一种独立的、客观的确认和咨询活动,包括鉴证、识别和分析问题以及提供管理建议和解决方案。狭义的数字化转型是指将企业经营管理和业务操作的各种行为、状态和结果用数字的形式来记录和存储,据此再对数据进行挖掘、分析和应用。广义的数字化转…

HTML入门:简单了解 HTML 和浏览器

你好,我是云桃桃。今天来简单了解一下 HTML 以及浏览器。 HTML 是什么? HTML(全称:Hypertext Markup Language)是一种标记语言,用于创建和呈现网页的结构和内容。 它由一系列标签(或称为元素…

小程序API能力集成指南——画布API汇总(五)

CanvasContext canvas 组件的绘图上下文。 方法如下(4): setLineWidth CanvasContext.setLineWidth CanvasContext.setLineWidth(number lineWidth) 功能描述 设置线条的宽度 参数 number lineWidth 线条的宽度,单位 px…

论文研读_多目标部署优化:无人机在能源高效无线覆盖中的应用(ImMOGWO)精简版

此篇文章为Multi-objective Deployment Optimization of UAVs for Energy-Efficient Wireless Coverage的论文学习笔记,只供学习使用,不作商业用途,侵权删除。并且本人学术功底有限如果有思路不正确的地方欢迎批评指正! 创新点 RD算法 混合…

热红外图像直方图修正显示

热红外图像的直方图修正是一种用于增强图像对比度和可视化细节的技术。下面是一个使用Python和OpenCV库实现直方图均衡化的示例代码: import cv2 import numpy as np# 读取热红外图像 image cv2.imread(thermal_image.png, cv2.IMREAD_GRAYSCALE)# 对图像进行直方…

.NetCore6.0实现ActionFilter过滤器记录接口请求日志

文章目录 目的实现案例:一.首先我们新建一个WebApi项目二.配置 appsettings.json 文件,配置日志存放路径三.创建 Model 文件夹,创建AppConfig类和ErrorLog类1.在AppConfig类中编写一个GetConfigInfo方法获取配置文件中的值2.在ErrorLog类中&a…

JAVA虚拟机实战篇之内存调优[1](内存泄露和溢出概念、常见场景、解决思路)

文章目录 内存泄漏(memory leak)内存溢出(Out of Memory): 内存泄漏的常见场景场景一:未删除用户数据场景二:分布式任务调度 解决内存溢出解决内存溢出思路发现问题 – Top命令发现问题 – Visu…

云计算OpenStack KVM迁移

动态迁移 static migration 静态迁移 cold migration 冷迁移 offline migration 离线迁移 live migration 动态迁移 hot migration 热迁移 online migration 在线迁移 衡量 整体迁移时间 服务器停机时间 性能影响(迁移后和其它客户机) 特点 负载均衡 解除硬件依赖…

算法刷题day22:双指针

目录 引言概念一、牛的学术圈I二、最长连续不重复序列三、数组元素的目标和四、判断子序列五、日志统计六、统计子矩阵 引言 关于这个双指针算法,主要是用来处理枚举子区间的事,时间复杂度从 O ( N 2 ) O(N^2) O(N2) 降为 O ( N ) O(N) O(N) &#xf…

three.js如何实现简易3D机房?(四)点击事件+呼吸灯效果

接上一篇: three.js如何实现简易3D机房?(三)显示信息弹框/标签:http://t.csdnimg.cn/5W2wA 目录 八、点击事件 1.实现效果 2.获取相交点 3.呼吸灯效果 4.添加点击事件 5.问题解决 八、点击事件 1.实现效果 2.…

postman登录鉴权之接口测试

一.背景 在做接口测试的时候,有些接口向后台请求数据的时候,是需要用户在登录情况下才有数据返回。 以电商平台为例,用户的个人中心,用户的订单列表,用户的支付信息等等,所有用户维度的数据都是需要登录态…

网络原理TCP_IP

文章目录 应用层自定义协议 传输层udp协议TCP协议1.确认应答2.超时重传3.连接管理建立连接, 三次握手断开连接, 四次挥手tcp的状态 4.滑动窗口5.流量控制6.拥塞控制7.延时应答8.携带应答9.面向字节流10.异常情况 网络层IP协议地址管理路由选择 数据链路层以太网 应用层 自定义…

okHttp MediaType MIME格式详解

一、介绍 我们在做数据上传时,经常会用到Okhttp的开源库,okhttp开源库也遵循html提交的MIME数据格式。 所以我们经常会看到applicaiton/json这样的格式在传。 但是如果涉及到其他文件等就需要详细的数据格式,否则服务端无法解析 二、okHt…
最新文章