Delphi 2009 + Unicode + Char-size

6
我刚刚获得了Delphi 2009,并之前读过一些关于由于转换为Unicode字符串可能需要进行修改的文章。 主要是提到sizeof(char)不再保证为1。 但是,为什么这会涉及字符串操作呢?
例如,如果我使用AnsiString:='Test'并使用String(现在是Unicode)做同样的事情,那么我得到Length()=4,这对两种情况都是正确的。 没有测试过,我相信所有其他字符串操作函数都以相同的方式行事,并在内部决定参数是Unicode字符串还是其他任何内容。
如果我进行字符串操作,为什么字符的实际大小会对我有所帮助? (当然,如果我将字符串用作字符串而不是存储任何其他数据)
感谢任何帮助! Holger
7个回答

5
使用Unicode时,字符串(string)的长度小于其字符(char)大小的总和。只要您不假设Char的SizeOf为1SomeString[x]的SizeOf为1(因为现在都是FALSE),也不尝试将byteschars互换,那么就不会有任何问题。如果您在把Bytes塞进CharsStrings时做了一些有创意的事情,那么您需要使用AnsiString
(无论长度如何,SomeStringSizeOf仍然为4,因为它本质上是一个带有一些编译器魔法的指针。)

4
人们在旧版Delphi代码中经常会不经意地将字符转换为字节。例如,在写入流时,当你将字符串写入流时,必须指定写入的字节数,但人们经常传递字符计数。请参见Chris Bensen的这篇文章以了解另一个例子。
人们在旧代码中还经常使用“string”来存储二进制数据进行这种隐式转换。在这种情况下,他们实际上想要字节,但数据类型却期望字符。D2009有更好的类型可用于此。

1

我没有尝试过Delphi 2009,但是正在使用逐渐转换到Unicode的fpc。我有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之前,这两个值是相等的)

0

如果你调用了Windows API,或者有遗留代码对str[0]进行incdec来改变其长度,这可能会成为一个问题。


0

字符的实际大小并不重要,除非你是在字节级别进行操作。


0
(当然,如果我只将字符串用作字符串而不用于存储其他数据)
这是关键点,你不会将字符串用于其他目的,但有些人会这样做。他们像使用数组一样使用字符串,因此他们(包括我在内)需要检查所有这些用途,以确保没有出现问题...

你说得对。我感到困惑是因为我读到了有关字符串操作时字符大小很重要的内容。当我使用字符串来存储除字符串以外的任何东西时,当然需要我自己正确处理它。 - Holgerwa

0
让我们不要忘记,有时候并不真正希望进行这种转换。比如说,在记录中存储一个GUID。GUID只能包含十六进制字符以及-和括号...使它们占用两倍的空间可能会对现有代码产生很大影响。当然,简单的解决方案是将它们改为AnsiString,并处理编译器警告,如果您对它们进行任何字符串操作的话。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接