Verständnisfrage: Prozedur-Variablen (ganz ohne Objekte)

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Bitschubser
Beiträge: 62
Registriert: Mo 27. Aug 2012, 15:43

Verständnisfrage: Prozedur-Variablen (ganz ohne Objekte)

Beitrag von Bitschubser »

Das hier funktioniert:

Code: Alles auswählen

type
 
  TMeineStruktur = record
    a : longint;
    Funktion : function : TMeineStruktur;
  end;
 
var
  Struktur : TMeineStruktur;
  hilf : function : TMeineStruktur;
 
function Test : TMeineStruktur;
begin
  Result.a := Random(123456);
  Result.Funktion := hilf;
end;
 
procedure TMyApplication.DoRun;
begin
  hilf := @Test;
 
  while not Terminated do begin
    if Struktur.Funktion = NIL then
      Struktur.Funktion:= @Test;
    Struktur := Struktur.Funktion();
  end;
 
end;
 
Wenn sich jetzt jemand wundert, wofür "hilf" überhaupt gut ist:

Das hier lässt sich nicht kompilieren:

Code: Alles auswählen

function Test : TMeineStruktur;
begin
  Result.a := Random(123456);
  Result.Funktion := @Test;
end;                                  
Error: Incompatible types: got "Pointer" expected "TMeineStruktur.<procedure variable type of function:<record type>;Register>"
bei Result.Funktion := @Test;

Das hier lässt sich zwar kompilieren, aber statt der Adresse von test landet nach dem ersten Funtionsaufruf irgendwas auf Struktur.Funktion:

Code: Alles auswählen

function Test : TMeineStruktur;
begin
  Result.a := Random(123456);
  Pointer(Result.Funktion) := @Test;
end;                                 
Bonuspunkte für den der weiß, warum ausgerechnet hier

Code: Alles auswählen

Struktur := Struktur.Funktion();
die () nötig sind, damit der Compiler das schluckt.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Verständnisfrage: Prozedur-Variablen (ganz ohne Objekte)

Beitrag von Michl »

Bei mir lässt sich auch der erste Codeschnipsel nicht kompilieren, erst wenn ich "Record" zu "Class" ändere. (FPC 2.7.1)

Bitschubser hat geschrieben:Bonuspunkte für den der weiß, warum ausgerechnet hier

Code: Alles auswählen

Struktur := Struktur.Funktion();
die () nötig sind, damit der Compiler das schluckt.
Mal sehen, ob ich mir den verdienen kann :wink:

Der Compiler weiss mit der Klammer, dass er die Function "Funktion" aufrufen soll, ansonsten versucht er die Adresse der Function zu beziehen.

Das dürfte so ziemlich das gleiche Problem sein, wie hier:

Code: Alles auswählen

function GetInt: Integer;
begin
  GetInt:=Random(100);
  GetInt:=GetInt * Random(100);    //hier wird "GetInt" wie "Result" behandelt
  GetInt:=GetInt() * Random(100);  //hier wird die Function GetInt erneut (rekursiv) aufgerufen 
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  Caption:=IntToStr(GetInt);
end; 

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

marcov
Beiträge: 1102
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Verständnisfrage: Prozedur-Variablen (ganz ohne Objekte)

Beitrag von marcov »

Code: Alles auswählen

 
  Pointer(Result.Funktion) := @Test;
 
Ich denke das ist falsch. Es holt der wert von Result.Funktion auf, und interpretiert diesen Wert als Pointer.

Es ist einfacher kleine Programme zu machen, und mit -al zu compilieren und sich den Assembler an zu sehen.

Code: Alles auswählen

 
function Test : TMeineStruktur;
begin
  Result.a := Random(123456);
  Result.Funktion := @Test;
end;      
 
Es sieht danach aus das "function test" hier nicht im Scope ist. (sollte aber?) Möglich eine Ausnahme.

Code: Alles auswählen

 
Struktur := Struktur.Funktion();
 
Auch sehr merkwürdig.
Zuletzt geändert von Lori am So 4. Jan 2015, 14:49, insgesamt 1-mal geändert.
Grund: richtiger Highlighter

marcov
Beiträge: 1102
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Verständnisfrage: Prozedur-Variablen (ganz ohne Objekte)

Beitrag von marcov »

marcov hat geschrieben:

Code: Alles auswählen

 
function Test : TMeineStruktur;
begin
  Result.a := Random(123456);
  Result.Funktion := @Test;
end;      
 
Es sieht danach aus das "function test" hier nicht im Scope ist. (sollte aber?) Möglich eine Ausnahme.
Ah, jetzt erinnere ich mich. "test" ist hier die Funktionsresult, nicht der Funktion selbst.

Code: Alles auswählen

 
Struktur := Struktur.Funktion();
 
Struktur.Funktion und die Zurückgabe davon sind beide Funktions Typen. Also man muss () hinzufügen um an der Compiler deutlich zu machen was gemeint ist.
Ich wusste das nicht, ich dachte das das nur nötig ist wenn die Funktions Typen echt dasselbe sind.
Zuletzt geändert von Lori am So 4. Jan 2015, 14:49, insgesamt 1-mal geändert.
Grund: richtiger Highlighter

Antworten