Die Delphi-Anweisung "for ... to" läuft vom Endwert bis zum Startwert

7

Ich schreibe eine einfache App in Embarcadero Delphi 2010. Ein einfacher Code mit zwei Zyklen:

%Vor%

Laut Watch List beginnt die Variable "i" im zweiten Zyklus mit dem Wert 256 und geht auf 0 (256, 255, 254, ..., 0), aber die Elemente des Arrays sind korrekt (0, 1, 2, 3 , ...). Variable "i" nur lokal deklariert, keine globalen Variablen. Warum passiert das? Ist es normales Verhalten?

    
Alexey Petrov 18.02.2016, 07:46
quelle

2 Antworten

13

Die kurze Antwort ist wegen der Compiler-Optimierung. Die lange Antwort lautet:

In Ihrem Code Pascal hat die Ganzzahl I zwei (eigentlich drei) Zwecke. Erstens ist es die Schleifen Steuerungsvariable (oder Schleifenzähler), dh es steuert, wie oft die Schleife ausgeführt wird. Zweitens fungiert es als Index für das Array a . Und in der ersten Schleife fungiert es auch als der Wert, der den Array-Elementen zugewiesen ist. Bei der Kompilierung zu Maschinencode werden diese Rollen von verschiedenen Registern bearbeitet.

Wenn die Optimierung in den Compiler-Einstellungen festgelegt ist, erstellt der Compiler Code, der die Steuervariable von einem Startwert auf Null herunterzählt, wenn dies möglich ist, ohne das Endergebnis zu ändern . Dies ist der Fall, weil ein Vergleich mit einem Wert ungleich Null vermieden werden kann und somit schneller ist.

In der folgenden Disassemblierung der ersten Schleife können Sie sehen, dass die Rollen der Variablen I folgendermaßen behandelt werden:

  • Register eax fungiert als Schleifenkontrollvariable und value Array-Elementen zugewiesen
  • Register edx ist ein Zeiger auf ein Array - Element (um 4 erhöht (Bytes) pro Runde)

Demontage:

%Vor%

Da eax zwei Rollen hat, muss es aufwärts zählen. Beachten Sie, dass für die Schleifenzählung drei Befehle für jede Schleife erforderlich sind: inc eax , cmp eax, jnz I5db69d000100 und I .

Bei der Disassemblierung der zweiten Schleife werden die Rollen der Variablen eax ähnlich wie in der ersten Schleife behandelt, außer dass edx den Elementen nicht zugewiesen ist. Daher dient die Schleifensteuerung nur als Schleifenzähler und kann nach unten laufen.

  • Register dec eax ist eine Schleifenkontrollvariable
  • Register jnz I5db6b5 ist ein Zeiger auf ein Array - Element (um 4 erhöht (Bytes) pro Runde)

Demontage:

%Vor%

Beachten Sie, dass in diesem Fall nur zwei Befehle zum Verwalten der Schleifenzählung erforderlich sind: E2171 Variable 'i' inaccessible here due to optimization und %code% .

In Delphi XE7 wird im Watches-Fenster die Variable %code% während der ersten Schleife als inkrementierende Werte angezeigt, während der zweiten Schleife als %code% . In früheren Versionen erinnere ich mich daran, dass es dekrementierende Werte zeigt, von denen ich glaube, dass Sie sie sehen.

    
Tom Brunberg 18.02.2016, 10:11
quelle
8

Ich habe Ihren genauen Code kopiert, und wenn ich ihn ausführe, zählt die Variable "i" normalerweise für beide Zyklen. Bist du den zweiten Zyklus Schritt für Schritt gelaufen? Das "i" ist zu Beginn des zweiten Zyklus wirklich 256 wegen des ersten, aber sobald der zweite Zyklus beginnt, wird "i" zu 0 und zählt normalerweise zu 255.

Ich sehe nicht, wie oder warum würde es von 256 bis 0 zählen?

UPDATE: Ich habe nicht einmal daran gedacht, aber hier ist deine Erklärung, glaube ich: Ссылка

  

"Es ist eine Compiler-Optimierung - Sie verwenden nicht" I "in Ihrer Schleife   Daher dachte der Compiler an einen besseren Zählmodus. Ihre Schleifenanzahl   wird immer noch genau sein ... "

    
Vepir 18.02.2016 08:01
quelle

Tags und Links