Array mit var übergeben (Fehler oder OK)

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Acia6850
Beiträge: 74
Registriert: Mo 9. Okt 2023, 18:45
OS, Lazarus, FPC: Windows + WSL / Linux Debian Rasbian OS (L 3.4.0 FPC 3.2.3)
CPU-Target: 64Bit
Wohnort: LK Ludwigsburg

Array mit var übergeben (Fehler oder OK)

Beitrag von Acia6850 »

Hallo ich habe eine Frage zur Datenübergabe eines Array mit Var an eine Procedure !

Code: Alles auswählen


program cTestArray;

{$mode objfpc}{$H+}

uses
  {$IFDEF LINUX}
  cthreads,
  {$ENDIF}
  Sysutils, Classes;

Type
  TDataRec = Record
    sName : AnsiString;
    nNum  : Longint;
    nIdx  : Longint;
  end;

Var
  raData : Array[1..4] of TDataRec;

Procedure xSetArrayA(var arA : Array of TDataRec);
begin
  WriteLn('xSetArrayA High : ' + IntToStr(High(arA)));

  arA[1].sName:= 'VA1';
  arA[1].nIdx:=1;
  arA[1].nNum:=100;

  arA[2].sName:= 'VB2';
  arA[2].nIdx:=2;
  arA[2].nNum:=200;

  arA[3].sName:= 'VC3';
  arA[3].nIdx:=3;
  arA[3].nNum:=300;

  arA[4].sName:= 'VD4';
  arA[4].nIdx:=4;
  arA[4].nNum:=400;
end;

Procedure xSetArrayB;
begin
  WriteLn('xSetArrayB High : ' + IntToStr(High(raData)));

  raData[1].sName:= 'SA1';
  raData[1].nIdx:=1;
  raData[1].nNum:=100;

  raData[2].sName:= 'SB2';
  raData[2].nIdx:=2;
  raData[2].nNum:=200;

  raData[3].sName:= 'SC3';
  raData[3].nIdx:=3;
  raData[3].nNum:=300;

  raData[4].sName:= 'SD4';
  raData[4].nIdx:=4;
  raData[4].nNum:=400;
end;

Procedure xReadArray(N : Longint);
begin
  For N:=1 to N do begin
    WriteLn(Format('<%d> %s %d %d', [N,
                                     raData[N].sName,
                                     raData[N].nNum,
                                     raData[N].nIdx]));
  End;
end;

Procedure xRun;
begin
  xSetArrayA(raData);
  xReadArray(5);
  WriteLn('--------------');
  xSetArrayB;
  xReadArray(5);
end;

begin
  xRun;
end.        


Bei der ersten Procedure xSetArrayA wird das Array als Var übergeben und beschrieben.
Bei der zweiten Procedure xSetArrayB wird das Array direkt beschrieben.

Ausgabe mit Procedure xReadArray.

Ausgabe :



xSetArrayA High : 3
<1> 0 0
<2> VA1 100 1
<3> VB2 200 2
<4> VC3 300 3
<5> VD4 400 4
--------------
xSetArrayB High : 4
<1> SA1 100 1
<2> SB2 200 2
<3> SC3 300 3
<4> SD4 400 4
<5> VD4 400 4




Frage :

Warum ist der 1. Index des Arrays bei var übergabe 0 und bei direktem Zugrif 1 ?
Wiso hat das Array bei 'xSetArrayA 3 Indexe und bei 'xSetArrayB 4 Indexe.
Bei der Ausgabe 5 Index obwohl das Array nur 4 Indexe hat !

Bei der Ausgaben Schleife mit 4 fehlt bei xSetArrayA der letzte Eintag.
Bei der Ausgaben Schleife mit 4 fehlt bei xSetArrayB alles OK.
Bei der Ausgaben Schleife mit 5 fehlt bei xSetArrayB müsste es eine Fehler geben da
das Array nur eine grösse von 1..4 hat aber es hat 5 durch xSetArrayA.


Ich verstehe es nicht.

Grüße Acia6850

Benutzeravatar
theo
Beiträge: 11423
Registriert: Mo 11. Sep 2006, 19:01

Re: Array mit var übergeben (Fehler oder OK)

Beitrag von theo »

Du hast unterschiedliche Deklarationen des Array.

Probier mal so:

Code: Alles auswählen

  
  ...
  type TMyArr = Array[1..4] of TDataRec;

Var
  raData : TMyArr;

Procedure xSetArrayA(var arA : TMyArr);       
  ... 

Acia6850
Beiträge: 74
Registriert: Mo 9. Okt 2023, 18:45
OS, Lazarus, FPC: Windows + WSL / Linux Debian Rasbian OS (L 3.4.0 FPC 3.2.3)
CPU-Target: 64Bit
Wohnort: LK Ludwigsburg

Re: Array mit var übergeben (Fehler oder OK)

Beitrag von Acia6850 »

Danke für die schnelle Antwort.

So funktioniert es.

Das heist ich kann ein Array mit Var nur mit einer Typ Variabel übergeben.

var arA : Array of TDataRec kann nicht als übergabe Parameter für raData : Array[1..4] of TDataRec; benutzt werden.

Die Übergabe mit var arA : Array[1..4] of TDataRec geht ja auch nicht.

Benutzeravatar
Zvoni
Beiträge: 783
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 11 Pro (Laz4.3/FPC3.2.3)
CPU-Target: 64Bit
Wohnort: BW

Re: Array mit var übergeben (Fehler oder OK)

Beitrag von Zvoni »

Acia6850 hat geschrieben: Di 10. Nov 2026, 15:13 Danke für die schnelle Antwort.

So funktioniert es.

Das heist ich kann ein Array mit Var nur mit einer Typ Variabel übergeben.

var arA : Array of TDataRec kann nicht als übergabe Parameter für raData : Array[1..4] of TDataRec; benutzt werden.

Die Übergabe mit var arA : Array[1..4] of TDataRec geht ja auch nicht.
Weil ein "var arA : Array of TDataRec" on the fly ein dynamisches Array erzeugt, und dyn. Arrays beginnen IMMER bei 0.
Glaube mich zumindest daran zu erinnern, dass PascalDragon das mal so oder in ähnlicher Form erwähnt hat

mit "var" übergibst du ja eigentlich einen Adress-Zeiger auf das Ziel-Array (Im Regelfall auf das erste Element bzw. die Array-Variable selbst),
und ab dem Moment ist es deiner Prozedur egal, ob das Ziel-Array bei 1 oder bei 137 beginnt.

Ich lese dieses "Index 0 ist erstes Element eines Arrays" immer als "Adress-Offset"
MeinArray[0] --> Adresse der Array-Variablen + 0 * SizeOf(Array-Element) --> Array-Element wäre in deinem Fall der Record
MeinArray[1] --> Adresse der Array-Variablen + 1 * SizeOf(Array-Element)

Beispiel:
Adresse der Array-Variablen sei: 1000, und die Grösse deines Records 10 Bytes in Summe (Byte-Alignment nicht vergessen)
MeinArray[0] --> Adresse 1000
MeinArray[1] --> Adresse 1010
MeinArray[2] --> Adresse 1020
usw.

Warum es aber nicht knallt bei Aufruf von SetArrayA bzw. beim Zugriff auf Element 5 später kann ich nur vermuten:
Du rufst SetArrayA zuerst auf, und du weist eigentlich 5 Elemente dort zu, da wie du schon festgestellt hast, das Array in der Prozedur bei 0 beginnt, du Element 0 ignorierst, und dann mit Element 4 das fünfte hinzufügst.
Da das ganze per "var" übergeben wurde, kann ich nur vermuten, dass im Hintergrund ein SetLength ausgeführt wird, und diese Änderung dann an das äussere "originale" Array zurück reflektiert wird.

Würde ich aber als Bug betrachten, sofern du Range-Checks eingeschaltet hast!
Wenn die Range-Checks aus sind......
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Antworten