Der Code, den ich mir ansehe, ist dies:
%Vor% Meine Frage dreht sich um die Verwendung von numWords
. Verwendet das Laufzeitsystem diese Variable erneut oder weist es bei jedem Durchlauf durch die int
-Schleife ein neues for
zu? Wenn Sie sich fragen, warum ich das frage, bin ich ein Java-Programmierer, der in HPC einsteigen will und deshalb versuche, C zu lernen. Normalerweise weiß ich, dass Sie Code wie vermeiden wollen das ist also wirklich explorativ.
Ich bin mir bewusst, dass die Antwort wahrscheinlich auf den Compiler angewiesen ist ... Ich suche nach einer tieferen Erklärung als das. Nehmen Sie den Compiler Ihrer Wahl an.
Dies wird in C als "Block", "automatisch" oder "lokal" bezeichnet. Es ist eine Form von lexikalisches Scoping , dh ein Name bezieht sich auf seine lokale Umgebung. In C ist es von oben nach unten, was bedeutet, dass es passiert, wenn die Datei geparst und kompiliert und nur sichtbar ist, nachdem sie im Programm definiert wurde. Wenn die Variable den Gültigkeitsbereich verlässt, ist der lexikalische Name nicht mehr gültig (sichtbar) und der Speicher kann wiederverwendet werden.
Die Variable wird in einem lokalen Gültigkeitsbereich oder in einem Block definiert, der durch geschweifte Klammern { /* block */ }
definiert wird. Dies definiert eine ganze Gruppe von C- und C99-Idiomen wie:
Es gibt Feinheiten wie:
%Vor%und:
%Vor%Es gibt Idiosynkrasien:
In dem von Ihnen geposteten Beispiel haben Sie sich nach int numWords = 0;
erkundigt und ob jedes Mal ein neues int
durch die Schleife zugewiesen wird. Nein, es ist nur ein int in einem Schleifenblock zugewiesen, aber die rechte Seite von =
wird jedes Mal ausgeführt. Dies kann nachgewiesen werden:
Kompilieren Sie das mit jedem gcc (clang, eclipse, usw.) kompatiblen Compiler mit deaktivierten Optimierungen ( -O0
) oder on. Die Adresse von t2 ist immer dieselbe.
Vergleichen Sie jetzt mit einer rekursiven Funktion:
%Vor% Die Adresse von n
wird jedes Mal anders sein, weil bei jedem rekursiven Aufruf ein neues automatisches n zugeordnet wird.
Vergleiche mit einer iterativen Version von factorial, die zur Verwendung einer Schleifenblockzuweisung erzwungen wird:
%Vor% Abschließend haben Sie nach int numWords = 0;
in der for-Schleife gefragt. Die Variable wird in diesem Beispiel wiederverwendet.
Wie der Code geschrieben wird, verlässt sich der Programmierer auf die RH von int numWords = 0;
nach der ersten Ausführung und setzt die Variable auf 0 zurück, um sie in der folgenden while-Schleife zu verwenden.
Ihre Vorstellung davon, wie dies in Java funktioniert, könnte falsch verstanden werden - Java "zerteilt" auch nicht jedes Mal eine neue int
durch eine solche Schleife. Primitive Typvariablen wie int
werden im Java-Heapspeicher nicht zugewiesen und der Compiler verwendet denselben lokalen Speicher für jede Schleifeniteration.
Auf der anderen Seite, wenn Sie new
irgendetwas in Java jedes Mal durch eine Schleife aufrufen, dann ja, ein neues Objekt wird jedes Mal zugewiesen. In diesem Fall tun Sie das nicht. C wird auch nichts vom Heap zuweisen, es sei denn, Sie rufen malloc
oder ähnlich (oder in C ++, new
) auf.
Bitte beachten Sie den Unterschied zwischen automatic
und dynamic
Speicherzuweisung. In Java existiert nur letzteres.
Dies ist eine automatische Zuweisung:
%Vor%Dies ist eine dynamische Zuweisung:
%Vor% Die dynamische Zuweisung in C erfolgt nur explizit (wenn Sie malloc
oder seine Derivate aufrufen).
In Ihrem Code wird nur der Wert für Ihre Variable festgelegt, keine neue wird zugewiesen.
Aus Performance-Sicht wird es nicht wichtig sein. (Variablen werden Registern oder Speicherorten zugeordnet, so dass sie wiederverwendet werden müssen.)
Vom logischen Standpunkt aus gesehen, ja, es wird wiederverwendet, weil Sie es außerhalb der Schleife deklariert haben.
Aus logischer Sicht:
numWords
wird nicht in der äußeren Schleife wiederverwendet, da sie darin deklariert ist. numWords
wird in der inneren Schleife wiederverwendet, da sie nicht innerhalb von Der Gültigkeitsbereich der Variable numWords befindet sich innerhalb der for-Schleife. Genauso wie Java kann man die Variable nur innerhalb der Schleife benutzen, also müsste theoretisch ihr Speicher beim Beenden freigegeben werden - da sie in deinem Fall ebenfalls auf dem Stack ist.
Jeder gute Compiler würde jedoch denselben Speicher verwenden und die Variable einfach bei jeder Iteration auf 0 setzen.
Wenn Sie class
anstelle von int
verwenden, wird der Destruktor immer dann aufgerufen, wenn die for
Schleifen vorhanden sind.
Bedenke das auch:
%Vor%Die beiden hier erstellten Objekte befinden sich wahrscheinlich im selben Speicher.
Es wird jedes Mal durch die Schleife zugewiesen (der Compiler kann diese Zuweisung optimieren)
%Vor%Keine Garantie, dass alle 100 Zeilen die gleiche Adresse haben (obwohl sie dies wahrscheinlich tun).
Bearbeiten: Der C99-Standard , in 6.2.4 / 5 heißt es: "[the object] lifetime extends from entry into the block with which it is associated until execution of that block ends in any way."
und in 6.8.5 / 5 heißt es, dass der Körper einer for
-Anweisung tatsächlich ein Block ist ... also gilt der Absatz 6.2.4 / 5 .
Tags und Links c