Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is a Currency variable treated as a constant with FillChar in Delphi?

The following code should compile and does compile with many other types.
However, the compiler reports a "Constant object cannot be passed as var parameter" error - despite the variable quite obviously being a variable.

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

Similarly, the same problem occurs with a local variable in a procedure.

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

I suspect it has something to do with the fact that FillChar is a compiler magic procedure, and that Dest is an untyped var parameter. FillChar is the only routine I've found with this problem.

  • What causes this problem?
  • Are any other types affected?

In response to the inevitable "Why would you do that comments": We have a code generator that uses FillChar to generically initialise record structures & primitive types. It works with everything else, but unexpectedly failed with Currency. We do have workarounds, but it would be nice to understand the root cause, and know whether anything else is likely to cause us trouble.


Edit

From Jeroen's answer it is reasonable to conclude that the issue exists in all vesions of Delphi. Furthermore array's of Currency apparently exhibit a similar problem.

David's answer provides some nice workarounds.

One final workaround to consider is, modifying the generator to deal with Currency as a special case and simply set the Value := 0.

like image 229
Disillusioned Avatar asked Sep 10 '13 11:09

Disillusioned


2 Answers

What causes the problem?

A compiler bug. Please submit a QC report.

Are any other types affected?

Maybe. Try some to find out.


As for a work around I would write it like this:

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

or perhaps like this:

ZeroMemory(@LVar, SizeOf(LVar));

or even like this:

LVar := Default(Currency);

Personally I regard ZeroMemory as being more descriptive than FillChar.

like image 192
David Heffernan Avatar answered Sep 24 '22 08:09

David Heffernan


As requested by Craig Young:

It still occurs in Delphi XE4.
Report No: 118866 Status: Reported
Cannot perform FillChar on Currency variables
https://web.archive.org/web/20150322021442/http://qc.embarcadero.com/wc/qcmain.aspx?d=118866
It is similar to http://qc.embarcadero.com/wc/qcmain.aspx?d=87168 (not archived)

The workaround for this compiler bug for Delphi < 2009: use ZeroMemory or FillMemory from the Windows unit which works just as well as FillChar.

On the Delphi side, ZeroMemory and FillMemory use FillChar underneath which might be inlined as of Delphi 2006.
On the C++ side both use compiler macros.

It might be that this issue only happens with Currency because that is the only numeric compiler type that is scaled.
The issue does not reproduce with ordinal types, regular floating point types, and Comp.


Edit: The issue has been fixed in XE5 Update 2

like image 43
Jeroen Wiert Pluimers Avatar answered Sep 22 '22 08:09

Jeroen Wiert Pluimers