Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Case Frage (https://www.delphipraxis.net/23788-case-frage.html)

Nicodius 9. Jun 2004 18:45


Case Frage
 
Nur mal ne grundlegende Frage zu Delphi


Warum haben es die Delphiprogrammierer in eienr case struktur ausgeschlossen das case aus nem string zu bilden?

ich meine: das ist doch/ wäre dochmanchmal sehr praktisch.

mfg

Nicodius

Luckie 9. Jun 2004 18:50

Re: Case Frage
 
Sie haben es nicht ausgeschlossen. Es ist nicht möglich, da case nur mit ordinal Werten arbeitet.

Nicolai1234 9. Jun 2004 18:59

Re: Case Frage
 
Ich glaub er meint, warum case nur mit ordinaltypen arbeitet! Warum also Borland das so gebaut hat´?

Steve 9. Jun 2004 19:01

Re: Case Frage
 
öhm so verständnishalber mal ne kleine Beschreibung, was "ordinal" bedeutet, dann is das eigentlich klar ;)

Zitat:

Die "case"-Anweisung benötigt eine Variable von ordinalem Typ. Ordinale Typen sind abzählbare Typen. Abzählbar sind zB alle Integer-Typen, der Typ char etc.
mfg
Stephan

Nicodius 9. Jun 2004 19:01

Re: Case Frage
 
genau

sorry wegen falscher formulierung :stupid:


was ordinal heißt das weiß ich aber geerell würde eine casestruktur genauso gut mit strings funktionieren

da ZEICHEN K E T T E N also mehrere chars das hätten die leicht einbauen können :stupid:

Chewie 9. Jun 2004 19:11

Re: Case Frage
 
Liste der Anhänge anzeigen (Anzahl: 1)
case kann grundsätzlich nur konstante Ordinalwerte benutzen. Und der Grund wird klar, wenn man sich den erzeugten Code ansieht:

Delphi-Quellcode:
var
  i: Integer;
begin
  i := 1;
  case i of
    2: ShowMessage('2');
    3: ShowMessage('3');
  else
    ShowMessage('nix davon');
  end;
end;
Das erzeugt den im Anhang gezeigten Code. Da sieht man sehr schön, wie raffiniert der Compiler vorgeht: Er schreibt zunächst unser i in das Register EAX. Dann zieht er 2 davon ab. Nun prüft er, ob EAX gleich 0 ist, was der Fall gewesen wäre, wenn i=2 wäre. Nun zieht er noch eins und prüft wieder auf 0 (entspricht case 3). Ist bis hierher immer noch kein Sprung erfolgt, kommt ein unbedingter Sprung zur Anzeige von 'nix davon'.
Mit nicht konstanten Werten (geschweige denn mit Strings) wäre solch optimiertes Verhalten nicht möglich.
Und soweit ich weiß, machen das andere Sprachen wie C(++) oder Java auch nicht anders.

Nicodius 9. Jun 2004 19:15

Re: Case Frage
 
warum zieht er was ab?

Luckie 9. Jun 2004 19:17

Re: Case Frage
 
Lies, was Chewie schreibt:
Zitat:

Er schreibt zunächst unser i in das Register EAX. Dann zieht er 2 davon ab. Nun prüft er, ob EAX gleich 0 ist, was der Fall gewesen wäre, wenn i=2 wäre.
Um festzustellen ob ein case-Zweig zutrifft.

Chewie 9. Jun 2004 19:18

Re: Case Frage
 
Er prüft zunächst, ob i=2 ist. Dann prüft er, ob i=3 ist.
Wir schreiben nun unser i in EAX. Davon ziehen wir 2 ab. War i=2, steht jetzt eine 0 in EAX. War i<>2, könnte es 3 gewesen sein. Deshalb ziehen wir nochmal eins ab. War i=3, steht jetzt eine 0 drin. Sonst behandeln wir unseren else-Fall.
Jetzt verstanden?

Nicodius 9. Jun 2004 19:18

Re: Case Frage
 
aha .. aber was ist daran so rafiniert :stupid:


wie soll er es denn sonst machen?

.. naja um wieder OT zu werden: er kann so ja auch prüfen ob eine charKETTE vorhanden ist :?

Phoenix 9. Jun 2004 19:34

Re: Case Frage
 
Zitat:

Zitat von Nicodius
.. naja um wieder OT zu werden: er kann so ja auch prüfen ob eine charKETTE vorhanden ist :?

Nein, kann er nicht. Kannst Du strings abzählen?

Sidorion 24. Okt 2006 16:05

Re: Case Frage
 
Das raffinierte dabei ist, dass das zero-flag gesetzt wird, sobald der Register bei einer Operation Null wird. Das passiert automatisch und kostet keinen Befehl Microcode. Darüber hinaus gibt es kaum einen Befehl mit kürzerem Microcode, als JZ (Springe, wenn Zero-Flag gesetzt ist).
Man nutzt hier sozuzagen die Tatsache aus, dass verschiedene Befehle innerhalb der CPU unterschiedlich schnell verarbeitet werden.
Bei einem Vergleich von zwei Konstanten müsste die zweite erst in ein zweites Register geladen werden, und dann ein JE (Springe, wenn Register gleich) ausgeführt werden. Der JE macht im Microcode auch nix anderes, als die zweite von der ersten abzuziehen und ist genauso umfangreich wie die beiden Befehle im ersten Fall (DEC und JZ). Hierzu kommt dann noch bei jedem Case das Laden der Vergleichskonstante.

Phantom1 24. Okt 2006 16:29

Re: Case Frage
 
Ich wüsste auch gern mal warum das nicht geht, immerhin hat es ja früher in turbo pascal funktioniert!

mfg

Sidorion 24. Okt 2006 16:40

Re: Case Frage
 
Ganz sicher nur für Char, und das ist ein Ordinal.

Muetze1 24. Okt 2006 17:31

Re: Case Frage
 
Zitat:

Zitat von Phantom1
Ich wüsste auch gern mal warum das nicht geht, immerhin hat es ja früher in turbo pascal funktioniert!

Wie bitte? Höchstens mit einem Zeichen eines Strings, aber nicht mit einem gesamten (heutigen) ShortString.

/EDIT: Sidorion's Aussage übersehen. Er sagt ja schon das gleiche aus.

allgemein:
Wenn du eine Case Schleife mit mehreren Werten machst, dann baut sich der Compiler dazu eine Sprungtabelle. d.h. er bringt den Wert auf die Basis 0 und multipliziert ihn mit 4 (bzw. shl 2) um dann den entstandenen Wert als Offset in einer Tabelle mit Sprungadressen nutzen um die richtige Adresse zu ermitteln und dann dort hin zu springen. Dies ist eleganter und schneller als ständig mit Bedingungsabfragen bestimmte Anweisungen zu überspringen und sich so einer Bedingungsliste durch zu hangeln. Dies ist Geschwindigkeits- und Grössenoptimierter Code.

Wie sollte er sowas mit Strings bauen, wenn du niemals einen Ordinalen Typen hast den du zu einer solchen Adressierung benötigst. Bei Strings müsste er jeden einzelnen String an sich vergleichen um dann zu entscheiden ob er springt oder nicht. Dies fällt bei einer Sprungtabelle weg, da der Offset die Sprungadresse bestimmt und gleichzeitig der zu untersuchende Wert ist. Damit wird eine Abfrage des Wertes an sich unnötig.

Nachteile der Sprungtabelle: Wenn du "Lücken" in deinen Zweigen hast bzw. diese nicht aufsteigend sind, dann können Sprungtabellen nicht angewendet werden bzw. haben dadurch mehr Code bzw. Overhead, so dass es sich nicht mehr lohnt (Vorteil ist zu gering gegenüber dem alten Weg). Anderer Punkt: Die Grenzen des Ordinaltyps müssen vorher abgefragt werden, da er sonst schliesslich in's Nirvana springen würden, wenn die Sprungtabelle verlassen würde bei der Adressierung.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:42 Uhr.

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