何时在Free Pascal 3中将UnicodeString强制转换为字符串是否安全?

时间:2016-03-13 08:43:11

标签: unicode casting lazarus freepascal fpc

此单元测试在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返回UnicodeString。如果没有硬类型转换为字符串,编译器会警告不安全的转换:

  

警告:隐式字符串类型转换,可能会丢失数据   &#34;的UnicodeString&#34;到&#34; AnsiString&#34;

(使用Lazarus 1.6 / FPCUnit GUITestrunner测试)

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

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

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

1 个答案:

答案 0 :(得分:3)

一般来说,强制转换是不安全的,因为您仍在将UnicodeString转换为AnsiString,并且在编译时不知道AnsiString的编码。当您明确地执行此操作时,警告才会消失,编译器会假定您知道自己在做什么。

如果转换依赖于系统上的编码设置:它是UTF-8,那么Actual包含UTF-8编码的字符串,它可以正常工作,或者系统上的特定区域设置支持你的字符正在使用。如果您在具有e的系统上运行此代码。 G。 CP1250,它会失败。管理变量是DefaultSystemCodePage。在启动时,它由FPC RTL使用系统的编码进行初始化。但是,有一些框架(如LCL)会覆盖它并将其设置为e。 G。 UTF-8。

除了{$modeswitch unicodestrings}{$mode delphi}等于string之外,请使用unicodestring,因此编码将与区域设置无关。