Delphi

栏目: 编程语言 · 发布时间: 8年前

内容简介:Delphi

技术交流,DH解说.

以前写过一次,现在全部重写吧.比较基础了,高手莫笑.

记得有次在盒子上面看到有个人出的面试题,第一题就是:

AnsiString 和 WideString的区别.

好这里先留给大家想想,我讲完了,大家就应该知道了.嘿嘿.

首先分类:

1 ShortString ,可以容纳255个字符,主要为了老版本兼容

2 AnsiString ,可以容纳2的31次方个字符,D2009前默认的String类型

3 UnicodeString ,可以容纳2的30次方个字符,D2009及以后的默认String类型

4 WideString ,可以容纳2的30次方个字符,主要在COM中用的比较多.

好一个一个来讲:

ShortString

我们看到上面说的它可以容纳255个字符,但是它所占的空间是字符长度加1,为什么?

我们来看个例子:

Procedure TForm3.Btn1Click(Sender: TObject);
Var
  S: String[15];
Begin
  S:= 'HuangJackyAAAAA';
  ShowMessageFmt('%d', [Length(S)]);//15个字符
  ShowMessageFmt('%d', [SizeOf(S)]);//空间大小是16
End;

从上面的代码我们可以看出来,ShortString变量不是用的指针,而是直接就是内存块,不然SizeOf应该是4的.既然我们发现这个问题,我们肯定要去看下它的内存情况吧.

Delphi

我们可以发现它第一个字节用来存放的字符串的长度,所以它只能容纳255个字符,$FF,是吧.

那么把上面的代码改一下:

Procedure TForm3.Btn1Click(Sender: TObject);
Var
  S: String[15];
Begin
  S:= 'HuangJackyAAAAA';
  ShowMessageFmt('%d', [ord(S[0])]);//同样是15,哈哈.
  ShowMessageFmt('%d', [SizeOf(S)]);
End;

好的,这样我们已经掌握了第一种字符串了.

AnsiString

用同样的代码测试:

Procedure TForm3.Btn1Click(Sender: TObject);
Var
  S: AnsiString;
Begin
  S:= 'HuangJackyAAAAA';
  ShowMessageFmt('%d', [Length(S)]);//15
  ShowMessageFmt('%d', [SizeOf(S)]);//4
End;

说明变量S只是一个指针.

Delphi

好去看看这个地址:

Delphi

是吧,那么存放实际字符串这块内存是怎么样组织的呢?

偏移 -12 -10 -8 -4 0-长度-1 最后一位
内容 字符页码 每个字符大小 引用次数 字符串长度 实际内容 0

名词解释下:页码是什么?编码,UTF-8或者GBK这些.

我们知道字符串其实是一个对象,但是它的释放却不需要我们操心,那就是因为当引用次数为0的时候,编译器会自动释放.

我们上面说了AnsiString能容纳2的31次方个字符,是的,因为它的长度占了4个字节.

好我们写代码来测试一下:

Procedure TForm3.Btn1Click(Sender: TObject);
Var
  S: AnsiString;
  I:Integer;
Begin
  S:= 'HuangJackyAAAAA';
  I:=Integer(S);
  ShowMessage(IntToHex(PWord(I-12)^,4));//$03A8
  ShowMessage(IntToHex(PWord(I-10)^,4));//$0001,AnsiString中一个元素就一个字节
  ShowMessage(IntToHex(PCardinal(I-8)^,8));//$FFFFFFFF
  ShowMessage(IntToHex(PCardinal(I-4)^,8));//$0000000F
  ShowMessageFmt('%d', [Length(S)]);//15
  ShowMessageFmt('%d', [SizeOf(S)]);//4
End;

来贴图一张:

Delphi

和我们上面说的一样吧.

我们再去看下页码对应的是什么编码.$03A8就是936,查MSDN  936 - gb2312.哈哈.

UnicodeString的内存分布也是一样的.所以我感觉-12和-10加入主要为了UnicodeString服务的.因为Unicode里面的编码就很多了,每个元素的大小也根据编码不同有所不同的.

进入WideString之前,我们看看Delphi里面Length函数是怎么实现的.

Unit3.pas.40: I:=Length(S);
004B33CD 8B45FC           mov eax,[ebp-$04]
004B33D0 85C0             test eax,eax
004B33D2 7418             jz $004b33ec
004B33D4 8BD0             mov edx,eax
004B33D6 83EA0A           sub edx,$0a
004B33D9 66833A01         cmp word ptr [edx],$01
004B33DD 740D             jz $004b33ec
004B33DF 8D45FC           lea eax,[ebp-$04]
004B33E2 33C9             xor ecx,ecx
004B33E4 8B55FC           mov edx,[ebp-$04]
004B33E7 E8782EF5FF       call @InternalLStrFromUStr//因为我们不是用的Unicode所以这里会被跳过
004B33EC 85C0             test eax,eax
004B33EE 7405             jz $004b33f5
004B33F0 83E804           sub eax,$04 //对就是这样,偏移-4
004B33F3 8B00             mov eax,[eax] //取得它的值.是吧
004B33F5 8BD8             mov ebx,eax

反编译代码比Delphi7多太多了...

刚才在翻VCL代码的时候发现这样一个结构体:就是我们刚才说的

StrRec = packed record
    codePage: Word;
    elemSize: Word;
    refCnt: Longint;
    length: Longint;
  end;

WideString

从名字看,我们就知道了它一个字符肯定占2个字节了.哈哈,看例子:
Procedure TForm3.Btn1Click(Sender: TObject);
Var
  S: WideString;
Begin
  S:= 'HuangJackyAAAAA';
  ShowMessageFmt('%d', [Length(S)]);//15
  ShowMessageFmt('%d', [SizeOf(S[1])]);//2
  ShowMessageFmt('%d', [SizeOf(S)]);//4
End;

是吧,每个字符是2个字节,变量还是存放的指针.像AnsiString那样看看它实际数据在内存中的组织:

偏移 -4 0~长度-1 最后一个
内容 字符串长度 实际字符串内容 $00 $00

它同样是用4个字节来存储长度,但是它每个元素的大小是2个字节,所以它最多只能存储2的30次方个字符.

是不是想跑去看它的内存呢?

Delphi 长度是$1E??哈哈,长度要除2塞,因为这个长度是这个内存块的长度.

最后再多说一个:

PAnsiChar,PWideChar

这个就是C++里面的Char*,也就是末尾是0的那种字符,这个就比较单纯了,没有什么用专门的字节来存储长度,存储引用次数.所以很多地方我们能用PChar就用PChar,因为String类型的确很耗资源.

C++的人笑了,不要笑,CString一样有这个问题.

看个例子:

Procedure TForm3.Btn1Click(Sender: TObject);
Var
  S: PAnsiChar;
Begin
  S:= 'HuangJackyAAAAA';
  ShowMessageFmt('%d', [StrLen(S)]);//15
  ShowMessageFmt('%d', [SizeOf(S^)]);1
End;

看下内存,证明我没有忽悠人.

Delphi 前面和它不沾边了吧,尾巴是0结尾了吧.

开篇时候提的问题,大家也知道区别了吧.平时不要看字符串简单,其实我们了解得还不够.

从上面看出来,字符串使用的使用第一个元素下标是从1开始的不是0.其他使用的注意事项打算写在下一篇文章里面.

我是DH,貌似该吃午饭了.


以上所述就是小编给大家介绍的《Delphi》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design Accessible Web Sites

Design Accessible Web Sites

Jeremy Sydik / Pragmatic Bookshelf / 2007-11-05 / USD 34.95

It's not a one-browser web anymore. You need to reach audiences that use cell phones, PDAs, game consoles, or other "alternative" browsers, as well as users with disabilities. Legal requirements for a......一起来看看 《Design Accessible Web Sites》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具