热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Delphi的数据类型PChar

vars:string;pc:pchar;pb:pbyte;ac:array[1..100]ofchar;ab:array[1..100]ofbyte;i:integer;begi

var
s:string;
pc:pchar;
pb:pbyte;
ac:array[1..100] of char;
ab:array[1..100] of byte;
i:integer;
begin
s:='this is a test';
pc:=pchar(s); //string->pchar
pb:=pbyte(pc); //pchar->pbyte
for i:=1 to length(s) do
begin
ac[i]:=s[i]; //string->arrary of char
ab[i]:=byte(s[i]); //string->arrary of byte
end;
s:=pc; //pchar->string
s:=string(pb); //pbyte->string
s:=c; //arrary of char->string;
end;
move(buffer^,pchar(@rbuf)^,bufferlength);这样是对的不过我不是太了解pchar(@rbuf)^啥意思,有人能详细的说一下吗?
move(buffer^,//--取缓冲区指针解除引用的值;
pchar(@rbuf)^,//--@rbuf:这是取你的接收缓冲区的入口地址。相当于:@rbuf[0];
//pchar(@rubf)这是将你的接收缓冲区指针转换成PCHAR类型指针;也就是^char
//(pchar(@rbuf))^这样来看就列清楚了,解除指针引用后取值,实际上就是取指针地址内的值了。
bufferlength); move是在两个地址间拷贝数据,Move(D,S,Len)就是从S地址处开始拷贝Len个字节,然后在D地址开始的Len字节空间里存储。D,S并非一定要求是指针,比如
Move(buffer, rbuf, bufferlength);
或者
Move(buffer, rbuf[1], bufferlength);
或者更增加通用性:
Move(buffer, rbuf[Low(rbuf)], bufferlength);
都可以
来自Delphi Help 关键字String to PChar conversions
长字符串转换到PChar不是自动的。他们之间的不同点导致他们的转换存在问题。
1,长字符串是引用计数的,而PChar不是
2,赋值给长字符串是数据的拷贝,而PChar是指向数据的指针。
3,长字符串是空止符结尾,并包含有字符串的长度。而PChar是简单的空止符结尾。( 空止符结尾指以#0结尾)
procedure my_func(x: string);
begin
    some_proc(PChar(x)); //参照第一条,这么做自己负责x的生存期
end;
function title(n: Integer): PChar;
var
s: string;
begin
s := Format('title - %d', [n]);
Result := PChar(s); // 参照第2条,不能这么做
end;
关于Delphi 中 String (又叫 LongString、AnsiString) 与传统的 PChar的区别
1. string 是 Delphi 编译器内在支持的(predefined or built-in),是Delphi 的一个基本数据类型,而 PChar 只是一个指向零终止字符串的指针;
2. String 所存字符串是在堆(Heap)分配内存的,String 变量实际上是指向零终止字符串的指针,与此同时它还具有引用计数(reference count)功能,并且自身保存字符串长度,当引用计数为零时,自动释放所占用的空间。
3.将 string 赋值给另一个string,只是一个简单的指针赋值,不产生 copy 动作,只是增加string的引用计数;
4. 将一个 PChar 变量类型赋值给一个 string 变量类型会产生真正的 Copy 动作,即将 PChar 所指向的字符串整个copy到为string分配的内存中;
5. 将 string 赋值给一个 PChar 变量类型,只是简单地将string的指针值赋值给PChar 变量类型,而string 的引用计数并不因此操作而发生变化,因为这种情况 PChar 会对 string 产生依赖,当string 的引用计数为零自动释放内存空间后,PChar很可能指向一个无效的内存地址,在你的程序你必须小心对付这种情况。
6. 对 PChar 的操作速度要远远高于对 string 操作的速度,但 PChar 是一种落后的管理字符串的方式,而 string 则以高效的管理而胜出,PChar 它的存在只是为了兼容早期的类型和操作系统(调用 Windows API时会经常用到),建议平常使用 string。
你的那个demo程序我认为设计得非常糟糕,基本上说不清问题:
我设计的Demo程序:
procedure TForm1.Button1Click(Sender: TObject);
var
P: PChar;
S1, S2: string;
begin
S1 := '1234567ABCDE';
S2 := S1;
P := PChar(S1);
ShowMessage(IntToStr(SizeOf(S1))); //获得 S1 变量的大小
ShowMessage(IntToStr(integer(S1))); //获得 S1 指向的字符串的指针地址
ShowMessage(IntToStr(integer(P))); //获得 P 指向的字符串的指针地址
ShowMessage(IntToStr(integer(S2))); //获得 S2 指向的字符串的指针地址
S1 := P;
ShowMessage(IntToStr(integer(S1)));
ShowMessage(IntToStr(integer(P)));
ShowMessage(IntToStr(integer(S2)));
end;
分析代码要点:
S2 := S1 验证我总结的第3点
P := PChar(S1) 验证我总结的第5点
S1 := P 验证我总结的第4点
我这里按顺序显示的结果(您的结果可能与此不同,但不妨碍分析)
4 <= S1 变量的大小
4530660 <= S1 指向的字符串的指针地址
4530660 <= P 指向的字符串的指针地址
4530660 <= S2 指向的字符串的指针地址
9780484 <= S1 指向的字符串的指针地址 (地址发生变化)
4530660 <= P 指向的字符串的指针地址
4530660 <= S2 指向的字符串的指针地址
关于分析它的汇编代码,我认为没什么必要,先搞清楚这些基本的操作!
如果不考虑太多的话,我们采用简单的方法:
1:pchar to string:
ansistring a;
pchar b;
a=string(b);
2: string to pchar
ansistring a;
pchar b;
b=pchar(a);
不过类型不太安全的。


推荐阅读
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
author-avatar
Irises---_372
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有