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?
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:
eax
fungiert als Schleifenkontrollvariable und value
Array-Elementen zugewiesen 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,
und jnz
000100I
5db69dI
.
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.
dec eax
ist eine Schleifenkontrollvariable jnz I
5db6b5
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.
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 ... "