Frage zur Erzeugung lokaler Variablen
-
Nehmen wir an, wir haben folgende Funktion:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch( uMsg ) { case WM_NCCREATE: { int b = 0; // Integer Variable //weitere Anweisungen... break; } case WM_SIZE: { SIZE size = {LOWORD(lParam),HIWORD(lParam)}; // SIZE struct //weitere Anweisungen... break; } } return DefWindowProc(hwnd,uMsg,wParam,lParam); }
Wird die Integer Variable und der SIZE struct bei jedem Aufruf dieser Funktion sofort erzeugt, oder werden sie erst bei Bedarf erzeugt?
-
eigetlich bei bedarf.
wenne es für dich aber keine sichtbaren auswirkungen hat, kann sich der compiler es erlauben, sie auch zu funktionbeginn schon zu erzeugen, wenn er meint, es sei so schneller. und insbesondere kann er auch ganz drauf verzuchten, dafür speicherplatz auf dem stack zu verwenden, sondern die variablen in ein register stecken.mach du immer die variaben so lokal wie möglich. rauslegen für speed kann dann der compiler. andersrum, also reinlegen, kann er im allgemeinen nicht.
-
Erst beim Eintreten in den Block ´{´, in dem die Variablen definiert sind, werden sie erzeugt.Und mit Verlassen des Blocks ´}´ wieder zerstört.
Kannst du nachprüfen in dem du, statt einer Int-Variable, einmal ein Klassenobject ersttellst, das in seinem Con/Destruktor eine Meldung ausgibt.
Oder evtl. auch im Debugger.
-
@Sepp: Wie Volkard sagte, der Compiler kann das nach beliebem ändern, wenn es keine Auswirkung hat. Bei ner Klasse ist es schwieriger, weil natürlich C-tor und D-tor aufgerufen werden muss, aber wenn sich das nicht auf den Programmablauf auswirkt, kann er auch das ändern.
Es ist nicht vorgeschrieben, welchen Code der Compiler generiert.
-
Danke für die Infos! Meine Frage ist somit geklärt.
-
volkard schrieb:
eigetlich bei bedarf.
kennst du einen compiler, der das so macht ?
ich nicht und ich kann mir ehrlichgesagt auch nicht vorstellen, dass es einen gibt, da dadurch die stackverwaltung (bzw. die speicherzuordnung) sehr schwierig wird
-
[quote="0rp"]
volkard schrieb:
ich nicht und ich kann mir ehrlichgesagt auch nicht vorstellen, dass es einen gibt, da dadurch die stackverwaltung (bzw. die speicherzuordnung) sehr schwierig wird
normal:
int f() { if(rand()) { int a=rand(); retrurn rand()*rand()+b; } return rand(); }
und wenn er bock drauf hat:
int f() { int a; if(rand()) { a=rand(); retrurn rand()*rand()+b; } return rand(); }
sehe da null problemo.
ich sag ja nicht, daß er ständig und überall so tricks macht. aber ich würde es hier tun und compiler können heutzutage so triviale sachen. bin nicht sicher, aber ich glaube mir.
-
[quote="volkard]
sehe da null problemo.
[/quote]und was soll der code beweisen?
guggs dir halt mit deinem compiler an, un dann siehste, wie am anfang der funktion vor allem anderen code platz aufm stack für das a geschafft wird und nicht erst, wenn du das a benutzt
-
0rp schrieb:
guggs dir halt mit deinem compiler an, un dann siehste, wie am anfang der funktion vor allem anderen code platz aufm stack für das a geschafft wird und nicht erst, wenn du das a benutzt
Natürlich wird a gleich am Anfang auf den Stack gepackt, btw: ich würds in ein register packen
Denn da wird es ja definiert. Wo ich es verwende ist ja schnurz egal. Ich habe ja auch öfters Objekte die ich garnicht verwende (weil ich nur Ctor und Dtor brauche ;)).
Ich verstehe dein Problem ehrlich gesagt nicht. Der Compiler kann ja zu jeder Zeit ein push auf den Stack machen, bzw. eim mov in ein Register. Erklär mal genauer was dir unklar ist.
-
ich nicht und ich kann mir ehrlichgesagt auch nicht vorstellen, dass es einen gibt, da dadurch die stackverwaltung (bzw. die speicherzuordnung) sehr schwierig wird
wieso? Solange er den Scope nicht wegoptimiert ist das absolut kein Problem:
;{ push ebp mov ebp esp ;volatile int a push eax ;a=5 mov dword[ebp-4] 5 ;} mov esp ebp
oder
;{ push ebp mov ebp esp ;volatile int a; push eax ;volatile int b; push eax ;a=5 mov dword[ebp-4] 5 ;} mov esp ebp
Wenn man den Stack von unten betrachtet dann ist es egal wie hoch er ist.