Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Funktionsprinzip von Case...Of (Interne Arbeitsweise??) (https://www.delphipraxis.net/147716-funktionsprinzip-von-case-interne-arbeitsweise.html)

olee 14. Feb 2010 20:32


Funktionsprinzip von Case...Of (Interne Arbeitsweise??)
 
Hi,

Ich hätte mal eine Frage:

Wie arbeitet case...of ?

Ich würde das gerne wissen, da ich eine solche Funktion möglichst effiziert in meine Programmiersprache RUTIS einbauen will.

MFG

Wolfgang Mix 14. Feb 2010 20:48

Re: Funktionsprinzip von Case...Of (Interne Arbeitsweise??)
 
Statt etlicher IF-Abfragen so
Delphi-Quellcode:
Case ergebnis of
  1: Prozedur 1;
  2: Prozedur 2;
  ...
end; // Case

Helmi 14. Feb 2010 20:51

Re: Funktionsprinzip von Case...Of (Interne Arbeitsweise??)
 
ich denke eher er wollte wissen wie Delphi das intern übersetzt

Namenloser 14. Feb 2010 20:53

Re: Funktionsprinzip von Case...Of (Interne Arbeitsweise??)
 
@Wolfgang: Das war glaub ich nicht seine Frage ;)

@olee
Die case-Struktur erzeugt eine Sprungtabelle. Du kannst ja einfach mal testweiseeine Case-Struktur in Delphi schreiben, einen Breakpoint darauf setzen und dir dann den Assembler-Code anschauen. Es gab hier vor einigen Monaten mal einen Thread dazu, wo untersucht wurde, wie das die Tabelle genau angelegt wird und welche Optimierungen dabei vorgenommen werden. Leider finde ich den nicht mehr :wall:

Hawkeye219 14. Feb 2010 21:03

Re: Funktionsprinzip von Case...Of (Interne Arbeitsweise??)
 
Hallo,

es gibt fast nichts, was nicht schon mal untersucht wurde. Beispiele findest du in der DP oder hier.

Gruß Hawkeye

Namenloser 14. Feb 2010 21:48

Re: Funktionsprinzip von Case...Of (Interne Arbeitsweise??)
 
Zitat:

Zitat von Hawkeye219
Beispiele findest du in der DP

Genau den Thread hatte ich auch gesucht :thumb:

[edit]Ok, mit vor ein paar Monaten hab ich mich wohl vertan. das wird dann wohl der Zeitpunkt gewesen sein, an dem ich den Thread das erste mal gelesen habe :wink: [/edit]

olee 15. Feb 2010 00:08

Re: Funktionsprinzip von Case...Of (Interne Arbeitsweise??)
 
Ok ich denke ich muss meine Frage etwas genauer Ausdrücken ...

Erstmal muss ich sagen, dass dieser Artikel von Lemmy1 recht interessant war und mir auch geholfen hat.

Aber soweit wie die Technik da in Post #2 erklärt wurde, war ich auch schon....

Das Problem das sich mir stellt ist mit diesen Wertebereichen wie z.B.

Delphi-Quellcode:
  case AChar of
    'a'..'z', 'A'..'Z', '_' :
    begin
      Tu_Dies;
    end;
    '0'..'9', '.' :
    begin
      Tu_Das;
    end;
  end;
Bei diesem Beispiel bin ich mir noch nicht so recht sicher, wie ich das lösen kann.

Mein bisheriger Ansatz wäre es, diese Teilbedingungen ('a'..'z', 'A'..'Z', '_') aufzuteilen in so 3 "virtuelle" case Abschnitte,
wovon 2 jeweils zu dem mit dem eigentlichen Code springen würden.

MFG

Namenloser 15. Feb 2010 00:14

Re: Funktionsprinzip von Case...Of (Interne Arbeitsweise??)
 
Zitat:

Zitat von olee
Mein bisheriger Ansatz wäre es, diese Teilbedingungen ('a'..'z', 'A'..'Z', '_') aufzuteilen in so 3 "virtuelle" case Abschnitte, wovon 2 jeweils zu dem mit dem eigentlichen Code springen würden.

Wäre auch mein erster Gedanke. Ggf. kann man bei relativ kurzem Code, den Code auch einfach x-fach einfügen - so ähnlich wie eine Inline-Funktion.

himitsu 15. Feb 2010 06:05

Re: Funktionsprinzip von Case...Of (Interne Arbeitsweise??)
 
Zitat:

'a'..'z', 'A'..'Z', '_' :
Hier mußt du ja nur den Vergleichsteil aufteilen.
Selbst a..b kannst du ja nicht auf einemal auswerten und brauchst praktisch mehrere Vergleiche.
Unten hab ich jetzt nur ein a..b drin, aber im Prinzip wird da ja dann einfach nur alles nacheinander verglichen und dann in das eine zugehörige CASE gesprungen.


Es gibt im Prinzip mehrere Möglichkeiten, wie es Delphi und seine Verwandten intern lösen.

Ich schreib es jetzt mal in Pascal, statt ASM, damit's verständlicher/einfacher ist:

- direkte Vergleiche
- oder berechnen und mit 0 vergleichen

- die Vergleiche vor den jeweiligen Blöcken
- oder über eine Sprungtabelle am Anfang, hier kann man den Wert die ganze Zeit in einem Register lassen und geht so die Liste sehr flott durch

Wenn die Werte "weit" mehr als 1 Schritt (wo man SUB statt DEC nutzen muß) liegen, dann kann man auch direkt vergleichen.
Liegen viele Werte nah beieinander, dann macht sich das Berechnen schon besser.

Für dich dürfte die Tabelle am Anfang besser sein,
aber wenn man selber den ASM-Code schreibt und öfters mal was verändert/erweitert/löscht,
dann wäre da die 1. Variante wiederum besser (in diesem Fall weniger fehleranfällig und übersichtlicher)

Das Ausgangsprodukt:
Delphi-Quellcode:
case value of
  1: xxx1;
  2..5: xxx2;
  6: xxx3;
  8: xxx4;
  else xxx5;
end;
Vergleich - keine Tabelle
Delphi-Quellcode:
temp := value; // falls value eine Berechnung oder Degleichen ist
if temp <> 1 then goto j2;
xxx1;
goto yend;
j2:
if temp < 2 then goto j3;
if temp > 5 then goto j3;
xxx2;
goto yend;
i3:
if temp <> 6 then goto j4;
xxx3;
goto yend;
i4:
if temp <> 8 then goto jelse;
xxx4;
goto yend;
jend:
xxx5;
yend:
Vergleich - keine Tabelle - unoptimales durch alles gespringe, dafür weniger vorausberechnungen nötig, um die Sprungtadressen anzupassen, da jedes CASE nur sich kennen muß.
Allerdings bibt es hier kein ELSE, außer man prüft dort so, als wäre es ein normales CASE auf alle Werte der anderen CASE, mit negativem Ergebnis, bzw. man führt eine weitere Temp-Variable "wurde-was-anderes-schon verarbeitet" mit.
Delphi-Quellcode:
temp := value; // falls value eine Berechnung oder Degleichen ist

if temp = 1 then goto j1;
goto j1end;
j1:
xxx1;
j1end:

if temp >= 2 then goto j2;
if temp <= 5 then goto j2;
goto j2end;
j2:
xxx2;
y2end:

if temp = 6 then goto j3;
goto y3end;
i3:
xxx3;
y3end:

if temp = 8 then goto j4;
goto y4end;
j4:
xxx4;
j4end:
Verrechnen - keine Tabelle
Delphi-Quellcode:
temp := value; // nötig, weil mit dem Wert ja gerechnet wird
dec(temp);
if temp <> 0 then goto j2;
xxx1;
goto yend;
j2:
dec(temp);
if temp <> 0 then goto j3;
dec(temp, 3);
if temp > 0 then goto j3;
xxx2;
goto yend;
i3:
dec(temp);
if temp <> 0 then goto j4;
xxx3;
goto yend;
i4:
dec(temp, 2);
if temp > 0 then goto jelse;
xxx4;
goto yend;
jend:
xxx5;
yend:
Vergleich - Tabelle
Delphi-Quellcode:
temp := value; // falls value eine Berechnung oder Degleichen ist
if temp = 1 then goto j1;
if (temp >= 2) and (temp <= 5) then goto j2;
if temp = 6 then goto j3;
if temp = 8 then goto j4;
//jelse:
xxx5;
goto yend;
j1:
xxx1;
goto yend;
j2:
xxx2;
goto yend;
i3:
xxx3;
goto yend;
i4:
xxx4;
yend:
Verrechnen - Tabelle
Delphi-Quellcode:
temp := value; // nötig, weil mit dem Wert ja gerechnet wird
dec(temp);
if temp = 0 then goto j1;
dec(temp, 4);
if temp < 0 then goto j2;
dec(temp);
if temp = 0 then goto j3;
dec(temp, 2);
if temp = 0 then goto j4;
//jelse:
xxx5;
goto yend;
j1:
xxx1;
goto yend;
j2:
xxx2;
goto yend;
i3:
xxx3;
goto yend;
i4:
xxx4;
yend:
Vergleiche auf 0 sind ja einfacher
und wenn man mit dem Wert rechnet, dann kann man das Berechnungsergebmis auch gleich noch mit ausnutzen und so den Vergleich sparen:
Delphi-Quellcode:
dec(temp);
if temp <> 0 then goto j3;
Code:
dec &temp
jnz @@j3

olee 15. Feb 2010 10:25

Re: Funktionsprinzip von Case...Of (Interne Arbeitsweise??)
 
Ohje...

Da werde ich einiges zu implementieren haben in RUTIS...

Vor allem wird es unangenehm, immer den Code vom Case-Abschnitt und dessen Bedingung gleichzeitig zu erstellen, da ich so
den Case-Code unten anfügen muss und dessen Bedingung weiter oben :pale:

Naja aber ich denke ich werde es hinbekommen :mrgreen:

Danke für die Hilfe! :thumb:

MFG


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:20 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz