Delphi中有多种字符串类型,常见的有

UnicodeString

AnsiString

ShortString

不同类型的字符串可以在赋值语句和表达式中混用,编译器会自动进行类型转换。但是在某些情况下可能会造成数据的丢失。(例如双字节字符转换成单字节字符的时候。)

 

一、Unicodestring

在目前的Delphi中,String类型等价于UnicodeString类型。
UnicodeString的长度只受到可用内存的限制。它使用UTF-16编码,所以绝大多数字符都是两个字节长度。少数特殊符号需要用到两个UTF-16编码来表示,这种表示方法称为代理对(Surrogate Pair)。
UnicodeString类型的变量本质上是一个指针,它指向一个结构体。这个结构体中包含以下信息:字符串,字符串的长度,引用次数,每个字符所占的字节数以及代码页。若把字符串指针所指的地址看作原点,则上面这些信息所在的内存地址为:

距离原点的偏移量

-12

-10

-8

-4

0

长度*单个字符的字节数

内容

代码页

单个字符所占的字节数

引用次数

字符串长度

第一个字符

结束字符(NULL)

因为UnicodeString类型的变量是一个指针,所以两个相同的字符串只需要指向同一块内存即可。当一个UnicodeString类型的变量被赋予一个新的值的时候,原先所指向的字符串的引用数减一,新字符串的引用数加一。若一个字符串的引用数为0,则这个字符串占用的内存被自动释放。这个操作被称为“引用计数”。

由于引用计数,字符串之间的赋值或者把字符串当做参数传递时,只会改变引用计数,没有任何数据被复制。假如有至少两个变量引用了同一块字符串数据,当其中一个变量试图改变字符串的内容时,系统会自动把这块字符串复制到新的内存中再进行更改,原内存区域引用数减一,其余内容不变。这被称为“写入时复制”技术。

二、AnsiString

AnsiString和UnicodeString的数据在内存中的组织结构完全一样。所以AnsiString也支持引用计数,写入时复制技术,它的长度也只受可用内存大小限制。

不同之处是,AnsiString是一种单字节字符串,而UnicodeString使用UTF-16编码,是双字节字符串。对于一个AnsiString类型的变量S来说,S[i]并不是第i个字符,而是第i个字节;Length(S)所显示的长度也不是字符串中的字符数,而是字节数。

举个例子

var

  S: AnsiString;

begin

  S:= '一只'+'abc'+'边牧';

  Writeln(Length(S)); {显示11,因为一个中文占两个字节}

  Writeln(S[6]); {显示b}

  Readln;

end.

 

三、ShortString

ShortString主要是为了和早期Pascal的String类型兼容。在系统内部定义中

type ShortString = String[255];

我们也可以自己定义

type TMyStr = String[Len] {其中,0<Len<=255}

注意,String后面加了中括号就不再是String类型而是ShortString了。

不同于UnicodeString和AnsiString,ShortString类型的变量不是指针而是字符串的实际内容。不论字符串长度有多少,它占用的内存固定为Len+1。这个Len并不是字符串的长度,而是定义类型时候 type TMyStr = String[Len]的Len。所以默认的ShortString变量占用256个字节。其中,首字节(编号为0)记录着字符串的长度,后面的字节记录着字符串的内容。如果赋给ShortString变量的值超过了它的最大长度,超出部分会被截去。

 

除此以外,还有WideString, UTF8String, RawByteString等,就不再一一介绍了。

 

posted on 2021-09-04 16:28  一只小边牧  阅读(382)  评论(0编辑  收藏  举报