[Gelöst] Wert-Funktionsergebnis direkt an Pointer Parameter übergeben.

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

[Gelöst] Wert-Funktionsergebnis direkt an Pointer Parameter übergeben.

Beitrag von Nimral »

Die Frage hat sich im Zusammenhang mit VirtualTreeView ergeben, hat aber mit dieser relativ komplizierten Komponente nichts zu tun, daher hier ein kleines Demo-Projekt, um das Problem zu zeigen.

In Worten: wenn ich eine Funktion habe, die einen Wert (TTestRec) zurückgibt, und eine Prozedur, die einen Pointer of TTestRec (PTestRec) erwartet, kann ich dann das Funktionsergebnis direkt auf den Pointer übergeben, oder muss ich den Umweg über eine Zwischenvariable gehen.

Hier das Demo-Projekt:

Code: Alles auswählen

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Spin, StdCtrls;

Type
  TTestRec = Record
    Name:String;
    Value:Integer;
  end;
  PTestRec = ^TTestRec;


type

  { TForm1 }

  TForm1 = class(TForm)
    Edit1: TEdit;
    SpinEdit1: TSpinEdit;
    procedure FormCreate(Sender: TObject);
  private

  public
    Procedure DisplayValues(ATestRec:PTestRec);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

function MakeTestRec(AName:String;AValue:Integer):TTestRec;

begin
  Result.Name := AName;
  Result.Value := AValue;
end;

procedure TForm1.DisplayValues(ATestRec: PTestRec);

begin
  Edit1.Text := ATestRec^.Name;
  SpinEdit1.Value := ATestRec^.Value;
end;

procedure TForm1.FormCreate(Sender: TObject);

var
  tr: TTestRec;

begin
  // Das klappt ....
  tr := MakeTestRec('Test 1',100);
  DisplayValues(@tr);
  // Das alles nicht ...
  DisplayValues(@MakeTestRec('Test 2',200));
  DisplayValues(@(MakeTestRec('Test 2',200)));  
  DisplayValues(Pointer(MakeTestRec('Test 2',200)));  
end;

end.
Ich denke, der Compiler versucht dann, die Adresse der Funktion zu übergeben, dass ich das Ergebnis der Funktion meine würde ich ihm gerne mitteilen, aber ich weiß nicht, ob Pascal das kann.

Danke mal wieder,

Armin.
Zuletzt geändert von Nimral am Mo 2. Aug 2021, 08:15, insgesamt 1-mal geändert.

Benutzeravatar
Aidex
Beiträge: 60
Registriert: Do 24. Sep 2020, 07:02
OS, Lazarus, FPC: Win10 64bit, Laz v2.0.10
CPU-Target: AMD64

Re: Wert-Funktionsergebnis direkt an Pointer Parameter übergeben.

Beitrag von Aidex »

Definiere es hier einfach als "const"-Paramenter vom Typ TTestRec (nicht PTestRec), dann wird intern mit dem Zeiger gearbeitet, soweit ich weiß. Alternativ als "var"-Parameter.
procedure TForm1.DisplayValues(const ATestRec: TTestRec);

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Wert-Funktionsergebnis direkt an Pointer Parameter übergeben.

Beitrag von Socke »

Nimral hat geschrieben:
So 1. Aug 2021, 13:54
In Worten: wenn ich eine Funktion habe, die einen Wert (TTestRec) zurückgibt, und eine Prozedur, die einen Pointer of TTestRec (PTestRec) erwartet, kann ich dann das Funktionsergebnis direkt auf den Pointer übergeben, oder muss ich den Umweg über eine Zwischenvariable gehen.
Du musst über die Zwischenvariable gehen. Ansonsten bräuchte es schon eniges an Compiler Magic um den Record auch hinterher wieder aus dem Speicher zu räumen. So läuft das über die das ganz normale Aufräumen von Variablen.

Nachtrag:
Ein const-Parameter muss nicht zwangsläufig als Zeiger/Referenz übergeben werden. Hier darf der Compiler selbst entscheiden. Ist ein Zeiger zwingend erforderlich, kann man constref verwenden. Sollen die Werte geändert werden, ist var korrekt.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Nimral
Beiträge: 390
Registriert: Mi 10. Jun 2015, 11:33

Re: Wert-Funktionsergebnis direkt an Pointer Parameter übergeben.

Beitrag von Nimral »

Danke für die Info! Das mit Const und Constref war mir neu --> hat sich schon gelohnt, nochmals genauer hinzuschauen.

Das Interface ändern kann ich leider nicht, es geht im richtigen Leben wie schon angedeutet um eine fertige Komponente (VirtualTreeView), und die ist wie sie ist. Sie hat bei jedem Node als "Payload" so einen Pointer mit dran, ich muss da relativ oft Werte reinstopfen und dachte, als ich die x-te Zwischenvariable geschrieben habe, ob das nicht auch anders geht. Ohne große Hoffnung, aber man weiß ja nie.

Danke euch für eure Zeit

HG, Armin.

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Wert-Funktionsergebnis direkt an Pointer Parameter übergeben.

Beitrag von Socke »

Nimral hat geschrieben:
Mo 2. Aug 2021, 07:50
Node als "Payload" so einen Pointer mit dran, ich muss da relativ oft Werte reinstopfen und dachte, als ich die x-te Zwischenvariable geschrieben habe, ob das nicht auch anders geht.
Lazarus kann dir zuminedest die Variablendeklaration abnehmen:
procedure TForm1.FormCreate(Sender: TObject);
begin
// Cursor auf "tr", dann Strg+Shift+C
tr := MakeTestRec('Test 1',100);
DisplayValues(@tr);
end;
Sezte den Cursor im Quelltexteditor auf "tr" und drücke Strg+Shift+C. Die IDE erstellt dir in der Prozedur eine passende Variablendeklaration.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten