【问题标题】:Why is a Currency variable treated as a constant with FillChar in Delphi?为什么在 Delphi 中使用 FillChar 将 Currency 变量视为常量?
【发布时间】:2013-09-10 11:39:27
【问题描述】:

以下代码应该可以编译,并且可以与许多其他类型一起编译。
但是,编译器报告“常量对象不能作为 var 参数传递”错误 - 尽管 变量 很明显是一个 变量

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

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

procedure TestCurrency;
var
  LVar: Currency;
begin
  FillChar(LVar, SizeOf(LVar), 0);
end;

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

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

为了回应不可避免的“你为什么要这样做 cmets”:我们有一个代码生成器,它使用 FillChar 来一般地初始化记录结构和原始类型。它适用于其他一切,但意外地与货币失败。我们确实有解决方法,但最好了解根本原因,并了解是否有其他任何事情可能给我们带来麻烦。


编辑

Jeroen's answer 可以合理地得出结论,该问题存在于所有版本的 Delphi 中。此外,Currency 数组显然也存在类似问题。

David's answer 提供了一些不错的解决方法。

最后一个要考虑的解决方法是,修改生成器以将货币作为特殊情况处理,并简单地设置 Value := 0

【问题讨论】:

  • 它仍然出现在 Delphi XE4 中。报告编号:118866 状态:报告无法对货币变量 qc.embarcadero.com/wc/qcmain.aspx?d=118866 执行 FillChar 它类似于 qc.embarcadero.com/wc/qcmain.aspx?d=87168 Delphi Windows 单元中的 ZeroMemoryFillChar 一样有效。
  • @Jeroen猜猜ZeroMemory是如何实现的?
  • @JeroenWiertPluimers 谢谢。您可以重新发布作为答案吗?这些链接比单纯的评论更值得关注。
  • @CraigYoung 该报告现在被标记为已修复。我想知道该修复程序将在哪个版本的 Delphi 中发布。
  • @CraigYoung 它已在 Delphi XE5 Update 2 中得到修复;寻找118866:edn.embarcadero.com/article/43522

标签: delphi compiler-construction delphi-2007 delphi-5 fillchar


【解决方案1】:

问题的原因是什么?

编译器错误。请提交质控报告。

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

也许吧。试一试就知道了。


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

FillChar(Pointer(@LVar)^, SizeOf(LVar), 0);

或者像这样:

ZeroMemory(@LVar, SizeOf(LVar));

甚至像这样:

LVar := Default(Currency);

我个人认为ZeroMemoryFillChar 更具描述性。

【讨论】:

  • 请注意,如果您使用类型化地址运算符进行编译,则需要上面的Pointer 转换
  • 或者你可以使用双重类型转换FillChar(double(GVar), SizeOf(GVar), 0)。这是相对安全的,因为如果在将来的版本中出现SizeOf(GVar)<>SizeOf(double),您会收到一条错误消息。
  • @DavidHeffernan 感谢大卫,我们打算使用指针转换作为解决方法 - 我没有想到 ZeroMemory。但是,后者显然更好。至于Default(),在D2007上不可用。我确认它在 D2009 中可用,但找不到任何文档。 (系统的 XE4 在线文档中甚至都没有提到它。)你知道吗?
  • @CraigYoung 它应该出现在这里:docwiki.embarcadero.com/RADStudio/en/Delphi_Intrinsic_Routines 但我只能在这里找到它:docwiki.embarcadero.com/RADStudio/en/… 对于您的代码生成,ZeroMemory 是一个不错的选择。它将被内联到最后对FillChar 的调用中!
【解决方案2】:

作为requestedCraig Young

它仍然出现在 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 ZeroMemory 或 FillMemoryFillChar 一样有效。

在 Delphi 方面,ZeroMemoryFillMemory 在下面使用 FillChar,在 Delphi 2006 中可能是 inlined
在 C++ 端,两者都使用编译器宏。

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


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

【讨论】:

  • 一个公认的答案确实应该回答这个问题。你就不能这样吗。
  • 您发现的另一份质控报告不仅相似,而且完全相同。它还将Currency 变量传递给FillChar。该变量恰好是数组的一部分,但vaArray[viSize]Currency。所以你的新QC报告是骗人的。也就是说,两者都不是很好的报告。你为什么不提交SSCCE?您提交了所有多余的绒毛,而不是这个问题中漂亮的 SSCCE。
  • @DavidHeffernan 我以这种方式制定了 QC,因为我知道如何将 QC 条目添加到测试套件中。数组元素的编译器处理可能与简单变量不同,特别是对于编译器内置的特殊功能。我输入的 QC 可能与其他 QC 不同,编译器工程师肯定会指出:他们是确定的。我刚刚搜索(这次找到了!)我所追求的:一份相关报告。这个回答纯粹是对克雷格的一种姿态。如果您不喜欢它:投反对票和/或要求克雷格不接受它。
  • 我没有说我不喜欢它。我只是说你应该回答这个问题。只是一个小的编辑说这是一个编译器错误。至于QC报告,我听Allen说他更喜欢简单的报告。当然,他们需要在他们的测试套件中解决所有需要考虑的案例。外人做不到,只会错过。
  • 请注意QualityCentral has now been shut down,因此您无法再访问qc.embarcadero.com 链接。如果您需要访问旧的 QC 数据,请查看 QCScraper
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
  • 2021-11-15
  • 1970-01-01
  • 2010-10-15
相关资源
最近更新 更多