Recent

Author Topic: [SOLVED] FillChar on dynamic array: length reset to zero?  (Read 2161 times)

ljakoster

  • Newbie
  • Posts: 2
[SOLVED] FillChar on dynamic array: length reset to zero?
« on: February 14, 2024, 09:56:40 am »
Dear All,

First post here, so please be gentle :).

I am writing a pascal code that uses a number of dynamic arrays. After setting their length, I want to ensure all elements are zero, so I thought using FillChar would be perfect. However, it seems that FillChar then resets the length of these arrays to zero? Why? I couldn't not find anything on dynamic arrays nor on FillChar that explains why.

Things I've tried:
1) FillByte instead of FillChar
2) requesting different amounts of memory in FillChar (but I think it's correct like shown below)

any help would be very much appreciated.
This is a code that shows the problem. Fpc 3.2.2. on Linux Mint 21.2:
Code: Pascal  [Select][+][-]
  1. program testFillChar;
  2.  
  3. var r : array of real;
  4.  
  5. begin
  6.         SetLength(r, 10);
  7.        
  8.         Writeln('length of r:        ', Length(r));
  9.         writeln('size single element:', SizeOf(r));
  10.        
  11.         FillChar(r, SizeOf(r) * Length(r), 0); {now make sure all elements are 0}
  12.         Writeln('after fillchar, length: ',Length(r))  
  13. end.
  14.  


The output is:
length of r:        10
size single element:8
after fillchar, length: 0


Best wishes,
Jan-Anton
« Last Edit: February 14, 2024, 11:18:07 am by ljakoster »

alpine

  • Hero Member
  • *****
  • Posts: 1412
Re: FillChar on dynamic array: length reset to zero?
« Reply #1 on: February 14, 2024, 10:03:08 am »
r is actually a reference, so use r[0] as a destination and for sizeof.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

Zvoni

  • Hero Member
  • *****
  • Posts: 3398
Re: FillChar on dynamic array: length reset to zero?
« Reply #2 on: February 14, 2024, 10:05:17 am »
Code: Pascal  [Select][+][-]
  1. program testFillChar;
  2.  
  3. var r : array of real;
  4.  
  5. begin
  6.         SetLength(r, 10);
  7.  
  8.         Writeln('length of r:        ', Length(r));
  9.         writeln('size single element:', SizeOf(r));
  10.  
  11.         FillChar(r[0], SizeOf(r[0]) * Length(r), 0); {now make sure all elements are 0}
  12.         Writeln('after fillchar, length: ',Length(r))
  13. end.
On my system (FPC3.2.2-32-Bit !!)
Returns
length of r:        10
size single element:4
after fillchar, length: 10


EDIT: Me and alpine saying exactly the same... :-)

r is actually a reference, so use r[0] as a destination and for sizeof.
Better: FillChar has its first argument as "var" meaning: it's a reference (Pointer, memory-Address)
In TS original try he's passing the Memory-Adress of the array itself, but Fillchar needs the address of the first element
IIRC, that's a difference to C, where the address of the Array itself is actually the address of the first element.
Correct me if i'm wrong...
« Last Edit: February 14, 2024, 10:09:49 am by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 19258
  • Glad to be alive.
Re: FillChar on dynamic array: length reset to zero?
« Reply #3 on: February 14, 2024, 10:18:01 am »

IIRC, that's a difference to C, where the address of the Array itself is actually the address of the first element.
Correct me if i'm wrong...
C does not have dynamic arrays
Static Pascal arrays behave like C.
objects are fine constructs. You can even initialize them with constructors.

cdbc

  • Hero Member
  • *****
  • Posts: 2812
    • http://www.cdbc.dk
Re: FillChar on dynamic array: length reset to zero?
« Reply #4 on: February 14, 2024, 10:19:49 am »
Hi
edit: Thaddy you're too quick  :D
You're both absolutely right, it should be: fillchar(r[0],length(r),0);
Just for completeness, the same goes for strings: fillchar(s[1],length(s),#0);
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

wp

  • Hero Member
  • *****
  • Posts: 13554
Re: FillChar on dynamic array: length reset to zero?
« Reply #5 on: February 14, 2024, 10:42:44 am »
You're both absolutely right, it should be: fillchar(r[0],length(r),0);
No. The second argument of FillChar wants the number of bytes, not the length of the array. Since the array elements are "real" it must be length(r)*SizeOf(real) (or Length(r)*Size(r[0]) which causes an issue when length(r) = 0):
Code: Pascal  [Select][+][-]
  1.   FillChar(r[0], Length(r) * SizeOf(real), 0);
  2. // or: FillChar(r[0], Length(r) * SizeOf(r[0]), 0);

And "Size of single element" in above code is not SizeOf(r) (which is the size of a Pointer), but Sizeof(real) (or SizeOf(r[0]) ).
 
« Last Edit: February 14, 2024, 10:46:21 am by wp »

cdbc

  • Hero Member
  • *****
  • Posts: 2812
    • http://www.cdbc.dk
Re: FillChar on dynamic array: length reset to zero?
« Reply #6 on: February 14, 2024, 10:58:13 am »
Hi
@wp: Thank you for the correction, ofc it's the length * elementsize and that goes for e.g.: widestrings too(2 bytes per char).
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

ljakoster

  • Newbie
  • Posts: 2
Re: FillChar on dynamic array: length reset to zero?
« Reply #7 on: February 14, 2024, 11:16:16 am »
Wow, thanks so much! That was quick and makes a lot of sense. Very much appreciated!


rvk

  • Hero Member
  • *****
  • Posts: 7043
Re: FillChar on dynamic array: length reset to zero?
« Reply #8 on: February 14, 2024, 11:28:56 am »
No. The second argument of FillChar wants the number of bytes, not the length of the array. Since the array elements are "real" it must be length(r)*SizeOf(real) (or Length(r)*Size(r[0]) which causes an issue when length(r) = 0):
Code: Pascal  [Select][+][-]
  1.   FillChar(r[0], Length(r) * SizeOf(real), 0);
  2. // or: FillChar(r[0], Length(r) * SizeOf(r[0]), 0);
BTW. If length of r is 0, you don't need to do FillChar (there is nothing to fill ;) ).
So this would also be fine and will work for all possible array's, filled or not.
Code: Pascal  [Select][+][-]
  1. if Length(r) > 0 then FillChar(r[0], Length(r) * SizeOf(r[0]), 0);

wp

  • Hero Member
  • *****
  • Posts: 13554
Re: [SOLVED] FillChar on dynamic array: length reset to zero?
« Reply #9 on: February 14, 2024, 11:57:32 am »
The help file says:
"In case the length is set to a larger length than the current one, the new elements are zeroed out for a dynamic array."

Therefore FillChar is not needed at all if the array had not yet been used before.

In experiment:

Code: Pascal  [Select][+][-]
  1. program Project1;
  2. var
  3.   r: array of real;
  4.   i: Integer;
  5. begin
  6.   SetLength(r, 10);
  7.   for i := 0 to High(r) do
  8.     WriteLn(r[i]);
  9.   ReadLn;
  10. end.

Or more general:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. var
  4.   r: array of real;
  5.   i: Integer;
  6. begin
  7.   SetLength(r, 20);
  8.   for i := 0 to High(r) do
  9.     r[i] := Random;
  10.  
  11.   SetLength(r, 10);              // Reduce the length --> remaining elements are kept
  12.   for i := 0 to High(r) do
  13.     WriteLn(r[i]);
  14.   WriteLn;
  15.  
  16.   SetLength(r, 0);              // Clear array
  17.   SetLength(r, 10);             // Expand array --> zeroed
  18.   for i := 0 to High(r) do
  19.     WriteLn(r[i]);
  20.   WriteLn;
  21.  
  22.   ReadLn;
  23. end.  

« Last Edit: February 14, 2024, 12:03:52 pm by wp »

 

TinyPortal © 2005-2018