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.