Delphi 2009 + Unicode +字符大小
我刚得到Delphi 2009,并且之前已经阅读过一些有关修改的文章,因为改用Unicode字符串可能需要进行这些修改。
通常,要提到的是sizeof(char)不再保证为1.
但是,为什么这对于字符串操作会很有趣?
例如,如果我使用AnsiString:='Test'并对String(现在是unicode)执行相同操作,则得到Length()= 4,这在两种情况下都是正确的。
在没有测试的情况下,我确定所有其他字符串操作函数的行为均相同,并在内部确定该参数是否为unicode字符串或者其他。
如果我进行字符串操作,为什么char的实际大小会引起我的兴趣?
(当然,如果我使用字符串作为字符串并且不存储任何其他数据)
谢谢你的帮助!
霍尔格
解决方案
字符的实际大小无关紧要,除非我们在字节级别进行操作。
(Of course if I use strings as strings and not to store any other data)
这就是关键点,我们不会将字符串用于其他目的,但是有些人会使用。它们像数组一样使用字符串,因此它们(包括我在内)将需要检查所有此类用法,以确保没有损坏。
我没有尝试使用Delphi 2009,但使用的是fpc,它也正在缓慢切换到unicode。我有95%的把握,Delphi 2009的所有内容同样适用
在fpc中(当支持unicode时)将使诸如" length"之类的功能考虑代码页。因此,它将返回字符串的长度,就像"人类"看到的那样。例如,如果有两个汉字都占用Unicode中的两个字节的内存,则长度将返回2,因为字符串中有两个字符。但是该字符串将占用4个字节的内存。 (+用于引用计数和前导#0的内存,但不包括)
我们现在不能做的是:
var p : pchar; begin p := s[1]; for i := 0 to length(string)-1 do begin write(p); inc(p); end; end;
因为此代码将在两个中文字符示例中写入错误的两个字符。即,这两个字节是第一个"真实"字符的一部分。
简而言之:Length()不再返回为字符串分配的字节数,而是返回字符数。 (在切换到unicode之前,这两个值彼此相等)
人们经常在没有真正考虑的情况下,将旧的Delphi代码中的字符隐式转换为字节。例如,当写入流时。将字符串写入流时,必须指定要写入的字节数,但是人们通常会改用字符计数。有关另一个示例,请参见Chris Bensen的这篇文章。
人们经常进行此隐式转换和较旧代码的另一种方法是使用"字符串"存储二进制数据。在这种情况下,他们实际上需要字节,但是数据类型需要字符。 D2009为此提供了更好的类型。
别忘了有时确实不需要这种转换。例如,将GUID存储在记录中。 guid只能包含十六进制字符以及和括号,使它们占据两倍的空间可以对现有代码产生相当大的影响。确保简单的解决方案是将它们更改为AnsiString,并在对它们进行任何字符串操作时处理编译器警告。
使用Unicode SizeOf(SomeChar)<> Length(SomeChar)。本质上,字符串的长度小于其字符大小的总和。只要我们不假设SizeOf(Char)= 1或者SizeOf(SomeString [x])= 1(因为现在都为FALSE)或者尝试将字节与char交换,那么我们就不会有任何麻烦。在任何我们要进行创造性工作的地方,将Bytes填充为Chars或者Strings,那么我们将需要使用AnsiString。
(无论长度如何,SizeOf(SomeString)仍然为4,因为它本质上是具有某种编译器魔术性的指针。)