Einzelnen Beitrag anzeigen

Benutzerbild von jaenicke
jaenicke
Online

Registriert seit: 10. Jun 2003
Ort: Berlin
9.357 Beiträge
 
Delphi 11 Alexandria
 
#3

Re: for-Schleife gegen über while-Schleife

  Alt 21. Mär 2009, 03:58
Meine ganz klare Meinung: Die for-Variante ist in diesem Fall besser, weil vorher bekannt ist bis wo die Schleife maximal läuft.

Von der Lesbarkeit oder dem Schreiben des Codes ist das für mich persönlich kein großer Unterschied, sofern der Code ordentlich formatiert ist. Mehrfache Abbruchbedingungen benutze ich oft und die zu entwerfen ist auch kein Problem.

Der Grund ist ein anderer. Die for-Schleife kann vom Compiler sehr gut optimiert werden. Und der Zielwert ist bekannt und muss nicht jedesmal überprüft werden. Der Compiler kann ein passendes Register auswählen und die Zählweise optimieren. Das geht bei der While-Schleife nicht. Es muss jedesmal die vorgegebene Bedingung überprüft werden.
Ergebnis mit while:
Delphi-Quellcode:
Unit162.pas.36: i := 0;
004532C9 33F6 xor esi,esi
Unit162.pas.37: Result := False;
004532CB 33DB xor ebx,ebx
004532CD EB0D jmp $004532dc
Unit162.pas.41: CurrentPLZ := SonnenStundenListe[i];
004532CF 8B45FC mov eax,[ebp-$04]
004532D2 8B3CB0 mov edi,[eax+esi*4]
Unit162.pas.42: Result := CurrentPLZ = PLZ;
004532D5 3B7DF8 cmp edi,[ebp-$08]
004532D8 0F94C3 setz bl
Unit162.pas.43: Inc(i);
004532DB 46 inc esi
Unit162.pas.39: while (i < length(SonnenStundenListe) - 1) and (not Result) do
004532DC 8B45FC mov eax,[ebp-$04]
004532DF E84022FBFF call @DynArrayLength // !!! Wird jedesmal aufgerufen
004532E4 48 dec eax
004532E5 3BF0 cmp esi,eax
004532E7 7D04 jnl $004532ed
004532E9 84DB test bl,bl
004532EB 74E2 jz $004532cf
Unit162.pas.45: end;
004532ED 33C0 xor eax,eax
Ergebnis mit for:
Delphi-Quellcode:
Unit162.pas.53: Result := False;
0045333E 33DB xor ebx,ebx
Unit162.pas.55: for I := 0 to length(SonnenStundenListe) - 1 do
00453340 8B45FC mov eax,[ebp-$04]
00453343 E8DC21FBFF call @DynArrayLength // !!! Wird nur einmal aufgerufen
00453348 48 dec eax // überflüssig, siehe unten folgender Quelltext
00453349 85C0 test eax,eax
0045334B 7C15 jl $00453362
0045334D 40 inc eax
0045334E 33D2 xor edx,edx
Unit162.pas.57: CurrentPLZ := SonnenStundenListe[i];
00453350 8B4DFC mov ecx,[ebp-$04]
00453353 8B3C91 mov edi,[ecx+edx*4]
Unit162.pas.58: if CurrentPLZ = PLZ then
00453356 3BF7 cmp esi,edi
00453358 7504 jnz $0045335e
Unit162.pas.60: Result := True;
0045335A B301 mov bl,$01
Unit162.pas.61: Break;
0045335C EB04 jmp $00453362
Unit162.pas.63: end;
0045335E 42 inc edx
Unit162.pas.55: for I := 0 to length(SonnenStundenListe) - 1 do
0045335F 48 dec eax
00453360 75EE jnz $00453350
Unit162.pas.64: end;
00453362 33C0 xor eax,eax
Aus dem Grund ist die for-Schleife deutlich besser geeignet unter der Voraussetzung, dass man wie in diesem Fall vorher weiß wie lange die Schleife laufen soll (von der Abbruchbedingung abgesehen). In der Schleife muss dann hier in diesem Fall nur noch eine selbst geschriebene Bedingung ausgeführt werden.

Am optimalsten sieht das Ergebnis aus, wenn man direkt High benutzt, dann spart man auch noch das -1:
Delphi-Quellcode:
function IsPLZInArrayFor2(SonnenStundenListe: TSonnenStunden; PLZ: Integer): Boolean;
var
  i: Integer;
  CurrentPLZ: Integer;
begin
  Result := False;

  for I := 0 to High(SonnenStundenListe) do
  begin
    CurrentPLZ := SonnenStundenListe[i];
    if CurrentPLZ = PLZ then
    begin
      Result := True;
      Break;
    end;
  end;
end;
Delphi-Quellcode:
Unit162.pas.70: Result := False;
0045333E 33DB xor ebx,ebx
Unit162.pas.72: for I := 0 to High(SonnenStundenListe) do
00453340 8B45FC mov eax,[ebp-$04]
00453343 E8E421FBFF call @DynArrayHigh
00453348 85C0 test eax,eax
0045334A 7C15 jl $00453361
0045334C 40 inc eax
0045334D 33D2 xor edx,edx
Unit162.pas.74: CurrentPLZ := SonnenStundenListe[i];
0045334F 8B4DFC mov ecx,[ebp-$04]
00453352 8B3C91 mov edi,[ecx+edx*4]
Unit162.pas.75: if CurrentPLZ = PLZ then
00453355 3BF7 cmp esi,edi
00453357 7504 jnz $0045335d
Unit162.pas.77: Result := True;
00453359 B301 mov bl,$01
Unit162.pas.78: Break;
0045335B EB04 jmp $00453361
Unit162.pas.80: end;
0045335D 42 inc edx
Unit162.pas.72: for I := 0 to High(SonnenStundenListe) do
0045335E 48 dec eax
0045335F 75EE jnz $0045334f
Unit162.pas.81: end;
00453361 33C0 xor eax,eax
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat