| Autor |
Beitrag |
Der Michel
      
Beiträge: 38
|
Verfasst: Fr 14.03.03 10:10
Hallo,
wenn ich den folgenden Code ausführe fängt Delphi immer mit i = 20 an und zählt rückwärts. Kann mir jemand erklären woran das liegt? Ein Neustart von Delphi / Windows hat keine Abhilfe geschaffen.
Ich benutze Delphi 5.0 Professional ( Compilierung 6.18 ) mit UpdatePack1 und Windows 2000 Professional (Service Pack 2).
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm1.Button1Click(Sender: TObject); var aTmp : array[0..19] of string; i : integer; begin for i := 0 to High(aTmp) do begin if (aTmp[i] <> '') then Caption := aTmp[i]; end; end; |
Gruß,
Michel
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Fr 14.03.03 10:24
hallo du meinst eher
Quelltext 1:
| Caption := caption+aTmp[i]; |
ansonsten hast du mit deinem Code immer das letzte Zeichen drin
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
Der Michel 
      
Beiträge: 38
|
Verfasst: Fr 14.03.03 10:29
Hallo,
ja das stimmt schon, ist aber in diesem Fall egal, da es mir nur darum ging dass i rückwärts gezählt wird und der Code nur ein Beispiel ist.
Wenn ich allerdings schreibe:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure TForm1.Button1Click(Sender: TObject); var aTmp : array[0..19] of string; i : integer; begin // Nur als Beispiel, Code macht nicht wirklich Sinn for i := 0 to High(aTmp) do begin if (i = 1000) then Beep(); if (aTmp[i] <> '') then Caption := aTmp[i]; end; end; |
funktioniert alles bestens und i wird von 0 bis 19 gezählt.
Kann mir das jemand erklären?
Gruß,
Michel
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Fr 14.03.03 10:32
äh wie kommst du darauf, das von hintengezählt wird?
wenn du einen breakpoint setzt und die Schleife das erste mal durchlaufen wird, hat i ja noch keinen wert. sezt den haltepunkt in die Schleife, da sollte es anders aussehen
Mfg Frank
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
Der Michel 
      
Beiträge: 38
|
Verfasst: Fr 14.03.03 10:37
Hallo,
ich hab einen Breakpoint gesetzt bei "for i := 0 ..." und bin, als der Debugger dort ankam, in die nächste Zeile gegangen, und wenn ich mit der Maus auf i gezeigt hab stand da immer "i = 20", beim nächsten Schleifendurchlauf "i = 19" usw. Obwohl es (laut Code) ja eigentlich anders sein sollte. Du kannst es ja mal in Deinem Delphi ausprobieren ob es sich da auch so verhält, vielleicht muß ich das ja nur mal neu installieren?
Gruß,
Michel
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 14.03.03 11:39
Hat schon alles seine Ordnung. Da ist nichts geheimnisvolles dran. Da hat die Compileroptimierung von Delphi zugeschlagen.
Wird die Schleife denn korrekt abgearbeitet? Das ist doch das entscheidende.
|
|
Der Michel 
      
Beiträge: 38
|
Verfasst: Fr 14.03.03 11:55
Hallo,
ja, letztendlich wird es korrekt abgearbeitet. Obwohl er im ersten Schleifendurchlauf zwar anzeigt daß er an eine Funktion als Parameter 'aTmp[20]' übergibt (wo natürlich nur Müll drinsteht), kommt aber tatsächlich der Wert von 'aTmp[0]' an.
Aber als mir das zum ersten Mal aufgefallen ist hab ich ganz schön sparsam geguckt.
Gruß,
Michel
|
|
Klabautermann
      

Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: Fr 14.03.03 12:15
Hi,
ich mus Luckie zustimmen. Das wird an der Optimierung liegen. Bei deinem ersen Beispiel "erkennt" Delphi das es kein unterschied macht, ob die Schleife vorwärts oder rückwärts gezählt wird. Also lässt er sie rückwärts laufen, weil das schneller ist (im Assembler kann man nur auf 0 abfragen also mus Delphi beim hochzahlen immer das ergebnis einer Rechnung überprüfen, die 0 ergibt wenn die obere Grenze erreicht wurde beim runterzählen kann direckt auf 0 geprüft werden).
Ich deinem zweiten Beispiel reicht die "intelligenz" des Compilers einfach nicht mehr aus, um das ganze zu durchschauen.
Gruß
Klabutermann
Zuletzt bearbeitet von Klabautermann am Fr 14.03.03 14:15, insgesamt 1-mal bearbeitet
|
|
Der Michel 
      
Beiträge: 38
|
Verfasst: Fr 14.03.03 12:39
Hallo,
klingt einleuchtend.
Beim Auftreten des nächsten mysteriösen Phänomens weiß ich dann Bescheid.
Besten Dank.
Gruß,
Michel
|
|
AndyB
      
Beiträge: 1173
Erhaltene Danke: 14
RAD Studio XE2
|
Verfasst: Fr 14.03.03 17:21
Hier steht was der Compiler bei der for-Schleife macht.
_________________ Ist Zeit wirklich Geld?
|
|
Wolff68
      
Beiträge: 302
Erhaltene Danke: 1
WinXP home
D6 Prof
|
Verfasst: Fr 14.03.03 20:28
Das mit der Code-Optimierung stimmt zwar, und Delphi zählt dann gerne mal rückwärts. ABER: Eben in diesem Beispiel ist es eben NICHT Egal, ob vorwärts, oder rückwärts gezählt wird.
IF Tmp[i] <> '' then Caption := Tmp[i]
Daraus folgt, daß Du nach dem Durchlauf der Schleife den letzten, nicht leeren Eintrag im Caption stehen haben möchtest! Und nicht den ersten! Denn genau den bekommst Du angezeigt, wenn die Schleife runterzählt.
Also sollte sie Code-Optimierung in diesem Beispiel erkennen, daß es eben NICHT egal ist, ob hoch- oder runtergezählt wird.
Erkennt sie das nicht, würde das ganze bei mir schon unter die Rubrik BUG fallen.
_________________ "Der Mensch ist nicht was er sich vorstellt oder wünscht zu sein, sondern das was andere in ihm sehen."
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Fr 14.03.03 20:45
Jajn. Eigentlich schon. Andererseits auch nicht. Wenn es wichtig wäre, dann brächte man es nicht über eine Schleife zu jagen. Alos nicht so:
For ... To ... Do IF Tmp[i] <> '' then Caption := Tmp[i]
sondern so
Caption := Tmp[High(aTmp)]
Wenn also das eine wenig Sinn ergibt, wieso soll es dann einen Sinn ergeben den letzten Array zuzuweisen.
_________________ Popov
|
|
Wolff68
      
Beiträge: 302
Erhaltene Danke: 1
WinXP home
D6 Prof
|
Verfasst: Fr 14.03.03 21:40
Beispiel Tmp = ['','1','2','3','4','','','','8','','']
Dann wäre:
Tmp[High(Tmp)] = ''
For...to...If...<>'' ... = '8' (Wenn hochgezählt)
For...downto...If...<>'' = '1' (Wenn runtergezählt)
Oder seh ich das falsch?
_________________ "Der Mensch ist nicht was er sich vorstellt oder wünscht zu sein, sondern das was andere in ihm sehen."
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Fr 14.03.03 21:58
Du siehst das nicht falsch. Allerdings ist es nicht so, als ob man hier einen bestimmten Wert eines Arrays haben wollte:
Quelltext 1: 2: 3: 4:
| for i := 0 to High(aTmp) do begin if (aTmp[i] <> '') then Caption := aTmp[i]; end; |
Zugegeben, es soll der letzte nicht leere Wert sein. Aber anschinend ist es nicht so wichtig - denkt sich der Compiler.
Wenn ich mich erinnere, so hab ich auch mal das Problem gehabt. Ich glaube dammals hab ich das entweder per Inc gemacht oder per x - i.
_________________ Popov
|
|
Wolff68
      
Beiträge: 302
Erhaltene Danke: 1
WinXP home
D6 Prof
|
Verfasst: Fr 14.03.03 22:25
Egal was der Compiler denkt; Ich finde es schon wichtig, ob ich in meiner Steuererklärung nachher '1' oder '8' stehen hab...
Aber um hier mal die Gemüter zu beruhigen:
Ich hab das Beispiel mal nachgebaut und aTmp[2] := '2' und aTmp[8] := 8; mit eingefügt. (Damit im Array auch was drin ist)
Er zählt zwar i nun immer noch rückwärts, aber stellt das intern so um, daß doch das richtige rauskommt.
Ist echt lustig, wenn er plötzlich bei i = 18 dem Label eine '2' zuweist, und bei i = 12 kommt dann die 8
Probiert es mal aus. Hier der Code: Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.Button1Click(Sender: TObject); var aTmp : Array[0..19] of String; i : Integer; begin Label1.Caption := ''; aTmp[2] := '2'; aTmp[8] := '8'; for i := 0 to High(aTmp) do begin if (aTmp[i] <> '') then Label1.Caption := aTmp[i]; end; end; |
_________________ "Der Mensch ist nicht was er sich vorstellt oder wünscht zu sein, sondern das was andere in ihm sehen."
|
|
AndyB
      
Beiträge: 1173
Erhaltene Danke: 14
RAD Studio XE2
|
Verfasst: Sa 15.03.03 00:30
| Wolff68 hat folgendes geschrieben: | | Er zählt zwar i nun immer noch rückwärts |
Falsch. Die Schleife wird vorwärts durchlaufen. Den Link, den ich gepostet habe, habt ihr beide nicht angeschaut.
Der Compiler stellt den Code dahingehend um, dass der Zeiger auf das Array bei jedem Durchlauf auf das nächste Element zeigt. Um nun aber das Schleifenende zu ermitteln wird (aus Geschwindigkeitsgründen) eine Variable bis auf 0 heruntergezählt. Da der Debugger den Array-Zeiger schlecht anzeigen kann, nimmt er eben die erst beste Variable, und die wird eben auf 0 heruntergezählt.
Quelltext 1: 2: 3: 4: 5: 6: 7:
| var MyArray: array[0..100] of Integer; Index: Integer; begin for Index := 0 to 100 do MyArray[Index] := 10; end; |
Daraus mach der Compiler das:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| var MyArray: array[0..100] of Integer; Counter: Integer; // liegt auf der selben Speicheradresse wie "Index" HelperArray: PInteger; // ist in einem CPU Register ausgelagert begin HelperArray := @MyArray[0]; for Counter := 100 downto 0 do begin HelperArray^ := 10; Inc(HelperArray); // Zeiger auf das nächste Array-Element end; end; |
Wer ein Programm debuggt, sollte zuerst die Code-Optimierung ausschalten.
_________________ Ist Zeit wirklich Geld?
|
|
Brueggendiek
      
Beiträge: 304
Win 98, Win98SE, Win XP Home
D5 Std
|
Verfasst: Sa 15.03.03 01:11
Hallo!
| AndyB hat folgendes geschrieben: | | Wer ein Programm debuggt, sollte zuerst die Code-Optimierung ausschalten. |
Das ist schon deshalb wichtig, weil man sonst beim Debugger-Zugriff auf lokale Variablen gelegentlich bekommmt: "kann wegen Optimierung nicht zugegriffen werden" - der Compiler hat erkannt, daß die Variable nicht mehr benötigt wird und sie vorzeitig gelöscht. Ärgerlich, wenn ich nach einer Schleife mit 1000 Durchläufen den auf Result zugewiesenen Wert lesen will, ihn nicht mehr kriege und das Funktionsergebnis gleich weiterverarbeitet wird!
Gruß
Dietmar Brüggendiek
|
|