什么时候可以安全地将 UnicodeString 转换为 Free Pascal 3 中的字符串?

When is it safe to cast UnicodeString to string in Free Pascal 3?

此单元测试在 Delphi 模式下使用 Free Pascal 3.0 成功运行:

procedure TFreePascalTests.TestUTF8Decode;
var
  Raw: RawByteString;
  Actual: string;
begin
  Raw := UTF8Encode('关于汉语');

  Actual := string( UTF8Decode(Raw) ); // <--- cast from UnicodeString

  CheckEquals('关于汉语', Actual);

  // check Windows ANSI code page 
  CheckEquals(1252, GetACP);
  // check Free Pascal value (determines how CP_ACP is interpreted)
  CheckEquals(65001, DefaultSystemCodePage); 
end; 

UTF8Decode returns 一个 UnicodeString。如果没有将硬类型转换为字符串,编译器会警告不安全的转换:

Warning: Implicit string type conversion with potential data loss from "UnicodeString" to "AnsiString"

(使用 Lazarus 1.6 / FPCUnit GUITestrunner 测试)

根据http://wiki.freepascal.org/Character_and_string_types#String,字符串类型默认为 AnsiString(如果 {$H+} 开关设置为使用 AnsiString 而不是 ShortString)。

看起来 Free Pascal 将 Unicode 字符串存储在 AnsiString 变量中。 (即使没有演员,测试成功)

问题:随着测试的成功,我是否可以假设使用强制转换(以抑制警告)是安全的而不会有数据丢失的风险?

转换通常不安全,因为您仍在将 UnicodeString 转换为 AnsiString,而 AnsiString 的编码在编译时未知。警告只会在您明确执行时消失,并且编译器会假定您知道自己在做什么。

如果转换工作取决于您系统上的编码设置:它是 UTF-8,那么 Actual 包含字符串 UTF-8 编码并且它工作,或者您系统上的特定语言环境支持您正在使用的字符。如果您 运行 在带有 e 的系统上使用此代码。 G。 CP1250,会失效。控制变量是 DefaultSystemCodePage。在启动时,它由 FPC RTL 使用系统编码进行初始化。但是,有些框架(如 LCL)会覆盖它并将其设置为 e。 G。 UTF-8.

除了 {$mode delphi} 之外还使用 {$modeswitch unicodestrings},并且 string 等于 unicodestring,因此编码将与语言环境无关。