Autor Beitrag
Der Michel
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 38



BeitragVerfasst: 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).

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 2266
Erhaltene Danke: 4

Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
BeitragVerfasst: Fr 14.03.03 10:24 
hallo du meinst eher
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 38



BeitragVerfasst: 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 2266
Erhaltene Danke: 4

Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 38



BeitragVerfasst: 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



BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 38



BeitragVerfasst: 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. :wink:
Gruß,

Michel
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 38



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Fr 14.03.03 17:21 
Hier steht was der Compiler bei der for-Schleife macht.

_________________
Ist Zeit wirklich Geld?
Wolff68
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 302
Erhaltene Danke: 1

WinXP home
D6 Prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 302
Erhaltene Danke: 1

WinXP home
D6 Prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 302
Erhaltene Danke: 1

WinXP home
D6 Prof
BeitragVerfasst: 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. :shock:
Ist echt lustig, wenn er plötzlich bei i = 18 dem Label eine '2' zuweist, und bei i = 12 kommt dann die 8 :lol:

Probiert es mal aus. Hier der Code:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: 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.
ausblenden 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:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 304

Win 98, Win98SE, Win XP Home
D5 Std
BeitragVerfasst: 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