为什么在Delphi中使用FillChar将Currency变量视为常量?

Dis*_*ned 12 delphi compiler-construction delphi-2007 delphi-5 fillchar

以下代码应该编译并使用许多其他类型进行编译.
但是,编译器报告"Constant对象不能作为var参数传递"错误 - 尽管变量显然是一个变量.

program CurrencyConstant;
{$APPTYPE CONSOLE}
var
  GVar: Currency;
begin
  FillChar(GVar, SizeOf(GVar), 0);
end.
Run Code Online (Sandbox Code Playgroud)

同样,过程中的局部变量也会出现同样的问题.

procedure TestCurrency;
var
  LVar: Currency;
begin
  FillChar(LVar, SizeOf(LVar), 0);
end;
Run Code Online (Sandbox Code Playgroud)

我怀疑它与FillChar编译器魔术程序有关,这Dest是一个无类型的var参数. FillChar是我发现这个问题的唯一例程.

  • 是什么导致这个问题?
  • 是否有其他类型受到影响?

为了回应不可避免的"为什么要做那个评论":我们有一个代码生成器,它使用FillChar来一般地初始化记录结构和原始类型.它适用于其他一切,但出乎意料地失败了货币.我们确实有解决方法,但了解根本原因会很好,并且知道是否还有其他因素可能会给我们带来麻烦.


编辑

根据Jeroen的回答,可以合理地得出结论,这个问题存在于Delphi的所有部分中.此外,货币阵列显然也出现了类似的问题.

大卫的回答提供了一些很好的解决方法.

要考虑的最后一个解决方法是,修改生成器以处理Currency作为特例并简单地设置Value := 0.

Dav*_*nan 8

是什么原因造成的?

编译器错误.请提交质量控制报告.

是否有其他类型受到影响?

也许.试着找一些.


至于解决方法,我会这样写:

FillChar(Pointer(@LVar)^, SizeOf(LVar), 0);
Run Code Online (Sandbox Code Playgroud)

或者像这样:

ZeroMemory(@LVar, SizeOf(LVar));
Run Code Online (Sandbox Code Playgroud)

或者甚至喜欢这样:

LVar := Default(Currency);
Run Code Online (Sandbox Code Playgroud)

我个人认为ZeroMemory比描述更具描述性FillChar.


Jer*_*ers 2

根据克雷格·杨要求

在Delphi XE4中仍然出现这种情况。
报告编号:118866 状态:报告
无法对货币变量执行 FillChar
https://web.archive.org/web/20150322021442/http://qc.embarcadero.com/wc/qcmain.aspx?d=118866
它类似于 http://qc.embarcadero.com/wc/qcmain.aspx?d=87168(未存档)

Delphi < 2009 的此编译器错误的解决方法:使用Windows 单元中的ZeroMemoryFillMemory ,其工作效果与FillChar一样。

在 Delphi 方面,ZeroMemory并在 Delphi 2006 中FillMemory使用FillCharunderlying,这可能是内联的。
在 C++ 方面,两者都使用编译器宏。

此问题可能仅发生,Currency因为这是唯一可缩放的数字编译器类型。
对于序数类型、常规浮点类型和 ,不会重现该问题Comp


编辑:该问题已在XE5 Update 2中修复