Einzelnen Beitrag anzeigen

Gast
(Gast)

n/a Beiträge
 
#28
  Alt 3. Jul 2003, 22:24
Das Argument, daß C++ keine Unterscheidung kennt ist etwas naiv!
C wurde nämlich erfunden um Programmierern das Leben schwer zu machen.

Laßt mich mal ein wenig tiefer buddeln:

Delphi-Code. Es ist eine Prozedur und eine Funktion! ...
STDCALL wurde verwendet um den Unterschied anschaulicher darzustellen,
da Delphi ansonsten diverse Parametertypen (u.a. Integer) im Register
übergibt.
Delphi-Quellcode:
procedure prozedur(var i:Integer); // Anschaulicher!!!
begin
  i:=i+1;
end;

function funktion(i:Integer):Integer; stdcall; // Anschaulicher!!!
begin
  result:=i+1;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i:Integer;
begin
  i:=funktion(5); // ergebnis 6
  prozedur(i); // ergebnis 7
end;
Etwas Pseudo-Code:
Code:
procedure prozedur(var i:Integer); stdcall;
--------------
push   ebp            // EBP sichern
mov    ebp, esp       // Stack Frame
~~~~~~~~~~~~~~
mov    eax, [ebp+$08] // "EAX := @i"
inc    dword ptr [eax] // EAX^ := EAX^ + 1 // inc(EAX^)
~~~~~~~~~~~~~~
pop    ebp            // EBP wiederherstellen
ret    $04             // Rückkehren
--------------

function funktion(i:Integer):Integer; stdcall;
--------------
push   ebp            // EBP sichern
mov    ebp, esp       // Stack Frame
~~~~~~~~~~~~~~
mov    eax, [ebp+$08] // EAX := i
inc    eax            // i := i + 1 // inc(i)
~~~~~~~~~~~~~~
pop    ebp            // EBP wiederherstellen
ret    $04             // Rückkehren
--------------

procedure TForm1.Button1Click(Sender: TObject);
--------------
push   $05             // Parameterübergabe
call   0043C6AC       // Funktion Resultat in EAX
mov    [ebp-$04], eax // i := EAX
lea    eax, [ebp-$04] // EAX := @i // Adresse von "i" in EAX
call   0043C6A8        // Prozedur
--------------
Uns interessieren die Stellen zwischen den: "~~~~~~~~~~~~~~".

Also! Ich habe extra alles kommentiert. Bei Prozedur() sieht man, daß nicht
eine lokale Variable auf dem Stack, sondern die Speicheradresse an der "i"
liegt, verändert wird. Wenn man so will, wird folgendes übergeben:
  • @i ... hätte man also beispielsweise geschrieben Prozedur(iInteger); so wäre dies das Selbe!!!
  • @i sollte bekannt sein, es ist die Adresse an der "i" liegt.

Bei Funktion() hingegen wird zuerst der übergebene Wert, welcher auf dem
Stack als "lokale Variable" (lokale Variablen und Parameter sind eigentlich
intern das Gleiche) liegt, in das Register EAX übergeben. Da ordinale
Rückgabewerte bei den Aufrufkonventionen STDCALL und REGISTER jeweils in
EAX zurückgegeben werden, wird EAX nur noch inkrementiert.

WÜRDE MAN ALSO:
Prozedur(i:Integer) schreiben, dann wäre "i" eine "lokale Variable" und damit
ginge der Rückgabewert verloren! Hingegen bei obigem Beispiel (als Wieder-
holung) wird direkt PInteger(@i)^:=PInteger(@i)^+1; modifiziert.

Jetzt klar?

Du modifizierst nämlich direkt eine "globale" Variable. Für den Compiler ist
das gleich ... der kann jede Speicherstelle so referenzieren, auch wenn im
Delphi-Source die Variable "i" innerhalb von Button1Click() eine "lokale"
Variable ist.
  Mit Zitat antworten Zitat