2 Stimmen

Wie erhöht man den FOR-Schleifenwert in einer FOR-Schleifenanweisung?

Ich möchte wissen, wie man den Wert in einer FOR-Schleifenanweisung erhöht.

Dies ist mein Code.

function Check(var MemoryData:Array of byte;MemorySignature:Array of byte;Position:integer):boolean;
var i:byte;
begin
 for i := 0 to Length(MemorySignature) - 1 do
 begin
  while(MemorySignature[i] = $FF) do inc(i); //<< ERROR <<
  if(memorydata[i + position] <> MemorySignature[i]) then Result:=false;
 end;
 Result := True;
end;

Der Fehler ist: E2081 Zuweisung an die FOR-Schleifen-Variable 'i'.

Ich versuche, einen alten Code von C# nach Delphi zu übersetzen, aber ich kann das 'i' nicht erhöhen. Erhöhen 'i' ist nicht der einzige Weg zu gehen, aber ich möchte wissen, wo das Problem ist.

7voto

Michael Donohue Punkte 11704

In diesem Fall können Sie anstelle von inc(i) einfach ein 'continue' machen

7voto

Paul-Jan Punkte 16398

Ergänzend zu dem, was Lasse geschrieben hat, die Zuweisung an eine Schleifenvariable wird im Allgemeinen als Codegeruch betrachtet . Es erschwert die Lesbarkeit des Codes (wenn Sie die Schleife vorzeitig verlassen wollen, können Sie das viel klarer mit break/continue ausdrücken) und wird oft gemacht durch Zufall und verursacht alle möglichen unangenehmen Nebenwirkungen. Anstatt also den Compiler dazu zu bringen, seine Optimierungsfunktionen in jeder Schleife, in der die Schleifenvariable berührt wird, nicht auszuführen, hat Borland (jetzt CodeGear) in den sauren Apfel gebissen und die Zuweisung an die Schleifenvariable illegal gemacht.

Wenn Sie wirklich manuell mit Schleifenindizes herumspielen wollen, sollten Sie eine while-Schleife verwenden.

7voto

John Thomas Punkte 4015

Die anderen haben natürlich (im Allgemeinen) recht. Was nicht gesagt wurde, ist das 'i' in Ihrer Schleife nicht existieren. Delphi verwendet dafür ein CPU-Register. Deshalb können Sie es nicht ändern und deshalb sollten Sie eine 'for'-Schleife (nicht eine 'while'-Schleife) verwenden, weil die 'for'-Schleife viel schneller ist. Hier ist Ihr geänderter Code (nicht getestet, aber ich denke, dass Sie die Idee verstanden haben) - auch imho hatten Sie einige Fehler - auch diese wurden behoben:

function Check(var MemoryData:Array of byte;MemorySignature:Array of byte;Position:integer):boolean;
var i:byte;
begin
 Result := True; //moved at top. Your function always returned 'True'. This is what you wanted?
 for i := 0 to Length(MemorySignature) - 1 do //are you sure??? Perhaps you want High(MemorySignature) here... 
 begin
  if MemorySignature[i] <> $FF then //speedup - '<>' evaluates faster than '='
  begin
   Result:=memorydata[i + position] <> MemorySignature[i]; //speedup.
   if not Result then 
     Break; //added this! - speedup. We already know the result. So, no need to scan till end.
  end;
 end;
end;

...auch MemorySignature sollte eine 'const' oder 'var' haben. Andernfalls wird das Array so wie es jetzt ist kopiert. Das bedeutet Verlangsamung bei jedem Aufruf von 'Check'. Mit einer 'var' sind die Dinge bei unverändertem Code viel schneller, weil AFAIS die MemorySignature nicht verändert wird.

HTH

4voto

Mike Sutton Punkte 4198

Wenn Sie einen Schleifenzähler innerhalb einer Schleife ändern müssen, sollten Sie stattdessen eine while-Schleife verwenden.

Übrigens, Sie brauchen Ihr Ergebnis := Wahr Zeile die erste Zeile der Funktion sein, damit sie richtig funktioniert. So wie sie ist, wird sie immer True zurückgeben.

3voto

Lasse V. Karlsen Punkte 364542

Das Problem ist, dass der Compiler den ursprünglichen FOR-Schleifencode genommen hat und davon ausgeht, dass er weiß, was passiert, und daher den Code optimieren kann, indem er bestimmte CPU-Anweisungen ausgibt, die unter diesen Annahmen am schnellsten laufen.

Wenn man den Variablenwert ändern könnte, wären diese Annahmen hinfällig, und der Code würde nicht funktionieren.

Was Sie stattdessen tun sollten, ist nur eine separate Variable, die Sie tatsächlich verwenden, und verwenden Sie nur die FOR-Schleife Indizierung Variable zu verfolgen, wie viele Iterationen Sie derzeit ausgeführt haben.

Eine typische Optimierung könnte beispielsweise darin bestehen, CPU-Befehle zu schreiben, die die Iteration stoppen, wenn das Indexregister auf Null fällt, und die Schleife so umzuschreiben, dass sie intern abwärts statt aufwärts zählt, so dass der Code nicht mehr umgeschrieben werden kann, wenn Sie mit der Variable herumspielen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X