2012-06-13 3 views
14

Ist die Reihenfolge, in der Parameter berechnet werden, bevor eine Prozedur aufgerufen wird, in Delphi definiert?In Delphi werden Parameter in der Reihenfolge ausgewertet, wenn sie in eine Methode übergeben werden?

IOW, wenn ich diesen hässlichen Code (etwas gefunden, wie dies in einer Legacy-Anwendung) ...

function A(var err: integer): integer; 
begin 
    err := 42; 
    Result := 17; 
end; 

Test(A(err), err); 

... Testen ist garantiert Parameter erhalten (17, 42) oder könnte es auch sei (17, undefiniert)?


Edit:

Obwohl Davids Beispiel unterschiedliches Ergebnis mit 32-Bit und 64-Bit-Compiler zurückgibt, das (zum Glück) hat keinen Einfluss auf mein Legacy-Code, weil Test (A (err), err) nur speichert eine Adresse von 'err' im Register und es ist egal, ob der Compiler dies vor dem Aufruf von A (err) oder nach.

+2

Dieser Artikel von Interesse sein kann http://blog.barrkel.com/ 2008/04/c-evaluation-order-gotcha.html –

+1

Ein weiterer Beitrag dazu: http://stackoverflow.com/questions/3054526/delphi-compiler-directive-to-evaluate-arguments-in-reverse –

+0

@David, Mir war dieses C-Feature bewusst, und ich habe auf SO gelernt, dass Java und C# von links nach rechts ausgewertet werden, aber ich konnte mich nicht erinnern, wo Delphi dies dokumentiert hat (und wie wir erfahren haben, ist die Dokumentation falsch). – gabr

Antwort

12

Die Reihenfolge der Parameterauswertung in Delphi ist nicht definiert.

Als interessanter Beweis dafür, das folgende Programm hat je unterschiedlicher Ausgang, ob Sie als Ziel 32 oder 64 Bit Code:

program ParameterEvaluationOrder; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils; 

function SideEffect(A: Integer): Integer; 
begin 
    Writeln(A); 
    Result := A; 
end; 

procedure Test(A, B: Integer); 
begin 
end; 

begin 
    Test(SideEffect(1), SideEffect(2)); 
    Readln; 
end. 
+0

In Win64 wird die Reihenfolge der Auswertung durch die einzige Aufrufkonvention AFAIK definiert. In Win32 gibt es verschiedene Aufrufkonventionen, und sie geben nicht die Reihenfolge der Auswertung an, sondern nur die Reihenfolge der Übergabe. –

+4

@RudyVelthuis Nach bestem Wissen spezifizieren die Aufrufkonventionen die Reihenfolge von * passing *, geben aber nicht die Reihenfolge der * evaluation * an. Also bestreite ich diesen Kommentar. –

+0

IMO, Aufrufkonventionen können angeben, was sie wollen, WRT Aufruffunktionen. Wenn die Reihenfolge der Auswertung angegeben ist, aus welchem ​​Grund auch immer der Plattformentwickler hat, folgen Sie besser den Spezifikationen. Aber ich stimme zu, dass, AFAIK, bisher keine Aufrufkonvention dies getan hat. –

5

Edited: es scheint, dass der Compiler das Verhalten in der Hilfe beschrieben verletzen kann:

Von Calling Conventions Hilfethema (Hervorhebung von mir):

Das Register und pascal Konventionen übergeben Parameter aus links nach rechts; Das heißt, der Parameter ganz links ist ausgewertet und zuerst übergeben und der rechte Parameter wird ausgewertet und zuletzt übergeben.

+0

Es stellt sich heraus, dass die Dokumentation, die Sie verlinken, falsch ist. –

+0

macht es traurig, dass das Verhalten des Compilers nicht der einzigen offiziellen Dokumentationsquelle entspricht. – MBo

+0

stimme ich zu. Ich persönlich halte es für in Ordnung, dass der Bewertungsauftrag nicht definiert ist, aber die Dokumentation sollte nicht anders lauten. –

Verwandte Themen