Recent

Author Topic: Of Dynamic arrays and pointers...  (Read 1975 times)

navodar

  • Guest
Of Dynamic arrays and pointers...
« on: October 22, 2020, 08:22:55 pm »
Whats wrong with this code:

Code: Pascal  [Select][+][-]
  1. type
  2.   slist = record
  3.     ID:integer;
  4.     name:string[25];
  5.     surname:string[25];
  6.   end;
  7.  
  8.   Tslist=array of slist;
  9.  
  10.  
  11.  
  12. procedure Test;
  13. var
  14.     l:^tslist;
  15. begin
  16.   SetLength(l^, 1);
  17.  
  18.   l^[0].ID:=1;
  19.   l^[0].name:='MY NAME 1';
  20.   l^[0].surname:='MY SURNAME 1';
  21.  
  22.   SetLength(l^, 2);
  23.   l^[1].ID:=2;
  24.   l^[1].name:='MY NAME 2';
  25.   l^[1].surname:='MY SURNAME 2';
  26.  
  27. end;
  28.  
  29.  
  30.  

Handoko

  • Hero Member
  • *****
  • Posts: 5130
  • My goal: build my own game engine using Lazarus
Re: Of Dynamic arrays and pointers...
« Reply #1 on: October 22, 2020, 08:28:06 pm »
It should be:

Code: Pascal  [Select][+][-]
  1. type
  2.   slist = record
  3.     ID:integer;
  4.     name:string[25];
  5.     surname:string[25];
  6.   end;
  7.  
  8.   Tslist=array of slist;
  9.  
  10. procedure Test;
  11. var
  12.     l: tslist;
  13. begin
  14.   SetLength(l, 1);
  15.  
  16.   l[0].ID:=1;
  17.   l[0].name:='MY NAME 1';
  18.   l[0].surname:='MY SURNAME 1';
  19.  
  20.   SetLength(l, 2);
  21.   l[1].ID:=2;
  22.   l[1].name:='MY NAME 2';
  23.   l[1].surname:='MY SURNAME 2';
  24.  
  25. end;

navodar

  • Guest
Re: Of Dynamic arrays and pointers...
« Reply #2 on: October 22, 2020, 08:30:13 pm »
tnx, but what in the case i need to use pointer.  How then to initialize array ?

Handoko

  • Hero Member
  • *****
  • Posts: 5130
  • My goal: build my own game engine using Lazarus
Re: Of Dynamic arrays and pointers...
« Reply #3 on: October 22, 2020, 08:31:54 pm »
Use GetMem:

https://www.freepascal.org/docs-html/rtl/system/getmem.html

I used GetMem and FreeMem a lot long time ago. But now we have dynamic array and a wide selection of containers, you don't have to manually manage the memory. Use the fully-tested properly-optimized and professional-written containers:

https://wiki.freepascal.org/Data_Structures,_Containers,_Collections

Don't 'play' with pointers unless you really have to.
« Last Edit: October 22, 2020, 08:43:30 pm by Handoko »

navodar

  • Guest
Re: Of Dynamic arrays and pointers...
« Reply #4 on: October 22, 2020, 08:45:05 pm »
ok,  i set

Code: Pascal  [Select][+][-]
  1.  GetMem(l, 2*SizeOf(slist));

but don't know how to assign value to element now

this one won't work:

Code: Pascal  [Select][+][-]
  1. l^[0].ID:=1;

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Of Dynamic arrays and pointers...
« Reply #5 on: October 22, 2020, 08:45:54 pm »
Try this:
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. type
  6.   TRec = record
  7.     ID: Integer;
  8.     name: String[25];
  9.     surname: String[25];
  10.   end;
  11.  
  12.   PRec = ^TRec;
  13.  
  14.   TPRecArray = array  of PRec;
  15.  
  16. procedure Test(var anArr: TPRecArray);
  17. begin
  18.   SetLength(anArr, 2);
  19.  
  20.   New(anArr[0]);
  21.   anArr[0]^.ID := 1;
  22.   anArr[0]^.name := 'MY NAME 1';
  23.   anArr[0]^.surname := 'MY SURNAME 1';
  24.  
  25.   New(anArr[1]);
  26.   anArr[1]^.ID := 2;
  27.   anArr[1]^.name := 'MY NAME 2';
  28.   anArr[1]^.surname := 'MY SURNAME 2';
  29. end;
  30.  
  31. var
  32.   arr: TPRecArray = Nil;
  33.   p: PRec;
  34.  
  35. begin
  36.   Test(arr);
  37.   for p in arr do
  38.     Writeln(p^.ID,' ',p^.name,', ',p^.surname);
  39.   for p in arr do
  40.     Dispose(p);
  41.   WriteLn('Press Enter');
  42.   ReadLn;
  43. end.

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Of Dynamic arrays and pointers...
« Reply #6 on: October 22, 2020, 08:48:02 pm »
A dynamic array is a pointer, with a bunch of compiler magic behind it. A pointer to a dynamic array is therefore not different from a pointer to a pointer. For example:

Code: Pascal  [Select][+][-]
  1. type
  2.   TDynArray = array of Integer;
  3.   PDynArray = ^TDynArray;
  4.  
  5. var
  6.   localArray: TDynArray;
  7.   pLocalArray: PDynArray;
  8.   heapArray: PDynArray;
  9. begin
  10.   // this is a normal local variable of an dynamic array type
  11.   SetLength(localArray, 2);
  12.   localArray[0] := 0;
  13.   localArray[1] := 1;
  14.  
  15.   pLocalArray := @localArray;
  16.   // this points now to localArray
  17.   pLocalArray^[0] := 2;
  18.   // now localArray[0] is 2
  19.  
  20.   // you can also use this to allocate dynamic arrays on the heap
  21.   new(heapArray);
  22.   SetLength(heapArray^, 2);
  23.   heapArray^[0] := 1;
  24.   heapArray^[1] := 0;
  25.   // And dispose the memory afterwards
  26.   dispose(heapArray);
  27. end;

You can for example use pointer to dynamic arrays to circumvent the copy on write mechanism, but in the very most cases it is not that useful, especially if you consider that most dynamic arrays can used as pointers/c style arrays:
Code: Pascal  [Select][+][-]
  1. type
  2.   TDynamicArray = array of Integer;
  3.   PInteger = ^Integer;
  4.  
  5. var
  6.   localArray: TDynamicArray;
  7.   cStyleArray: PInteger;
  8. begin
  9.   SetLength(localArray, 2);
  10.   cStyleArray = @localArrray[0]; // casts also work, but this is shorter
  11.   cStyleArray[0] := 1; // sets localArray[0]
  12.   cStyleArray[1] := 2; // sets localArray[1]
  13.  
This way you can modify an array without triggering the copy on write mechanic.  Also external libraries can't handle FPC refcounted arrays, so you need to use these C-Style Arrays instead.
That said, doing this you loose information stored in the array like the length of the array, which a pointer to an array can preserve while still avoiding the copy on write problems

440bx

  • Hero Member
  • *****
  • Posts: 3944
Re: Of Dynamic arrays and pointers...
« Reply #7 on: October 22, 2020, 09:11:45 pm »
As Warfley above pointed out, a pointer to a dynamic array is a pointer to a pointer.  For this reason, it is a bit rare to have a pointer to a dynamic array since the reference to the array is already a pointer. 

Anyway, below is a modified version of the code you posted using a pointer to the dynamic array.

Code: Pascal  [Select][+][-]
  1. program DynamicArrayPointer;
  2.  
  3. type
  4.   slist = record
  5.     ID      : integer;
  6.     name    : string[25];
  7.     surname : string[25];
  8.   end;
  9.  
  10.   Tslist = array of slist;
  11.  
  12.  
  13.  
  14. procedure Test;
  15. var
  16.     TheArray        : tslist;   { TheArray is already a pointer to an array }
  17.     TheArrayPointer :^tslist;   { pointer to an array pointer               }
  18.  
  19. begin
  20.   SetLength(TheArray, 2);       { allocate space for the array              }
  21.  
  22.   TheArrayPointer := @TheArray; { get a pointer to the dynamic array        }
  23.  
  24.   TheArrayPointer^[0].ID      :=1;
  25.   TheArrayPointer^[0].name    :='MY NAME 1';
  26.   TheArrayPointer^[0].surname :='MY SURNAME 1';
  27.  
  28.   TheArrayPointer^[1].ID      :=2;
  29.   TheArrayPointer^[1].name    :='MY NAME 2';
  30.   TheArrayPointer^[1].surname :='MY SURNAME 2';
  31.  
  32.   TheArrayPointer := TheArrayPointer;
  33. end;
  34.  
  35. begin
  36.   Test();
  37. end.
  38.  
  39.  

HTH.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

navodar

  • Guest
Re: Of Dynamic arrays and pointers...
« Reply #8 on: October 22, 2020, 09:18:19 pm »
Thanks everyone on useful post.  I appreciate a lot.

 

TinyPortal © 2005-2018