请教各位大虾:如何判断一个字符串的最后一位是不是null(即#0)

L_Lei 2003-09-15 09:20:48
请教各位大虾:如何判断一个字符串的最后一位是不是null(即#0)
...全文
641 104 打赏 收藏 转发到动态 举报
写回复
用AI写文章
104 条回复
切换为时间正序
请发表友善的回复…
发表回复
RamjetZhang 2003-09-19
  • 打赏
  • 举报
回复
0 是当然有的,这样传string(AnsiString)给windows api 的时候,把字符串第一个字的地址传过去就是了--后面的'\0'就自动传给c-style的函数了,多省事。
telossoft 2003-09-19
  • 打赏
  • 举报
回复
不懂汇编,佩服 Raptor(猛禽) ,我只是习惯用DELPHI,我用copymemory到一个缓冲区去分析
telossoft 2003-09-19
  • 打赏
  • 举报
回复
抱歉,写错一行:
定义类型:
Pint = ^integer;
telossoft 2003-09-19
  • 打赏
  • 举报
回复
string是一个指针,长度4个字节
string是引用记数的,它记录有其长度
string是一个指针,指向具体字符串的第一个字符
为与pchar兼容,string自动在尾后加了#0
pchar(string) = pointer(string)
有朋友要问引用记数器和其长度记录在那里了?
定义类型:
Pint = integer^;
引用记数: pointer(integer(pointer(string)) - 8)
其长度: pointer(integer(pointer(string)) - 4)

引用记数: edit1.text:= inttostr(pint(integer(pointer(string)) - 8)^);
其长度: edit2.text:= inttostr(pint(integer(pointer(string)) - 4)^);

原来DELPHI在具体字符串的前面保存了string引用记数和长度

我在找工作,有合适的告诉我: QQ:45904680
猛禽 2003-09-17
  • 打赏
  • 举报
回复
相关的汇编函数:

@LStrFromPChar:根据一个PChar来创建一个String的Instance
@LStrFromPCharLen:根据一个长度来创建一个String的Instance
@NewAnsiString:根据Len创建一个新的String Instance
@GetMem:分配内存

有兴趣的可以自己在CPU Windows里看:)
猛禽 2003-09-17
  • 打赏
  • 举报
回复
偶看了风兄的建议,看了一下汇编代码。

基本上是这样:

当新建一个String并向它赋一个串值时:

首先,计算其串长度,得nLen,以前面那个17char的例子来说,就是$11(#17)
然后,根据nLen创建一个Instance
在NewInstance时,计算所需要空间:
nSize := ( nLen + 10 ) and ( -2 ); // nLen=$11时,nSize=$1A
估计上述算法是基于:加上8Byte的nRefCnt和nLen,及最后一个#0,然后按16bit Word对齐
然后,调用GetMem分配内存,设分配的地址为pAddr
其结构如下:
strAnsi = record
unknown : Integer;
nSize : Integer;
nRefCnt : Integer; // pAddr指向这里
nLen : Integer;
szBuf : Array [0..17] of char; // 包括最后的#0所占空间
end;
然后,将Result设置为pAddr+$8(即指向szBuf)
再把nLen赋给strAnsi.nLen,把1(refCnt)赋给strAnsi.nRefCnt

好啦,分析完毕,显然:
一个String的Instance中只包括:nRefCnt,nLen,szBuf三部分,前面的nSize是分配内存时留下的,至于nSize前面一个是什么东东,偶也不知道了,应该是DELPHI内存管理用的东东,这也就是为什么nSize总是会多出来的四个byte了。
blucecat 2003-09-17
  • 打赏
  • 举报
回复
zjqyb(风清扬*任它溺水三千,我只取一瓢饮*)

你能不能给大家分析一下你的结论怎样从汇编里面得来的?
现在小弟正在学汇编,请多指教,在此谢过
cll007 2003-09-17
  • 打赏
  • 举报
回复
我是菜鸟
我喜欢以上大虾们的这种辩论
能让人深入的了解Delphi底层的东西,有益我等菜鸟的健康成长
佩服
感谢大虾们
L_Lei 2003-09-16
  • 打赏
  • 举报
回复
看来这个问题大家还不是都很清楚啊,建议开个网络会议,大家都可以发言参与讨论
zjqyb 2003-09-16
  • 打赏
  • 举报
回复
s:='My name is delphi';
strAnsi = record
nSize: Integer;//4
nRef: Integer; //4
nLength: Integer;//4
szBuf: array[0..0] of Char; //4
end;
所以应该是4+4+4+4+17+1

blucecat 2003-09-16
  • 打赏
  • 举报
回复
s:='My name is delphi';//17个字节
按你给的结构,占用4+4+4+17+1=30个字节,没错吧?

我这样计算s占用空间:
integer(pointer((integer(@s[1])-12))^); //应该没错吧?
为什么占用了34个字节?
FrameSniper 2003-09-16
  • 打赏
  • 举报
回复
To BlueCat

AnsiString类型的结构如下:
strAnsi = record
nSize: Integer;
nRef: Integer;
nLength: Integer;
szBuf: array of Char;
end;

这是我前面给出的结构示意,和你说的4+4+4+17+1的结果有什么区别吗?
FrameSniper 2003-09-16
  • 打赏
  • 举报
回复
To Zjqyb

应该不是这个样子吧!
blucecat 2003-09-16
  • 打赏
  • 举报
回复
FrameSniper:我是按你的计算方式来的,请问另外4个字节在哪去了?
blucecat 2003-09-16
  • 打赏
  • 举报
回复
FrameSniper:
var
s:string;
itemp:integer;
begin
s:='My name is delphi';//17个字节
itemp:=integer(pointer((integer(@s[1])-4))^); //字符串长度等于17 正确
showmessage(inttostr(itemp));
itemp:=integer(pointer((integer(@s[1])-8))^); //引用计数等于1 正确
showmessage(inttostr(itemp));
itemp:=integer(pointer((integer(@s[1])-12))^); //占用空间等于34 不正确 应该是:4+4+4+17+1=30;
showmessage(inttostr(itemp));
end;

你如何解释?
blucecat 2003-09-16
  • 打赏
  • 举报
回复
var
s:string;
itemp:integer;
begin
s:='My name is delphi';//17个字节
itemp:=integer(pointer((integer(@s[1])-4))^); //字符串长度等于17 正确
showmessage(inttostr(itemp));
itemp:=integer(pointer((integer(@s[1])-8))^); //引用计数等于1 正确
showmessage(inttostr(itemp));
itemp:=integer(pointer((integer(@s[1])-12))^); //占用空间等于34 不正确 应该是:4+4+4+17+1=30;
showmessage(inttostr(itemp));
end;



FrameSniper你如何解释?
zjqyb 2003-09-16
  • 打赏
  • 举报
回复
4+4+4+1=13
FrameSniper 2003-09-16
  • 打赏
  • 举报
回复
To zjqyb

请教一个问题,如果一个AnsiString的内容是1234,那么你认为实际给这个字串分配的空间是多少?
blucecat 2003-09-16
  • 打赏
  • 举报
回复
当然指针是占用4个字节的空间
getmem应该是给指针指定一个可操作的地址范围(内存空间)
strcopy就应该是将具体的字符串copy到这个地址范围(内存空间)里,这个地址就是指针指向的地址

所以,大家都是正确的
zjqyb 2003-09-16
  • 打赏
  • 举报
回复
////
var p:pchar;
s:string;
s:='12345678';
分配Refcount(4)+存放实际长度(4)+实际字符串(8)+#0(1)
是不是这样分配空间可以去问Borland
p:=Pchar(s);
简单的PChar(s)强制转换,确实是没有再重新分配内存,因为S已经分配了内存
但是如果要复制它,则要分配Length(s)+1个空间
getmem(p,Length(s)+1);
strcopy(p,pchar(s));//p结尾自动加#0;

难道这还有疑问!!!
加载更多回复(84)

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧