Dies mag wie eine Anfängerfrage aussehen, aber ich bin daran interessiert, wie ein Compiler normalerweise Arrays mit variablen Dimensionen erstellt, wie im folgenden Programm.
%Vor%Nach dem, was ich gelernt habe, müssen in C alle Initializer-Werte konstant sein, so dass der Compiler weiß, wieviel Speicher in der Funktion zu reservieren ist, normalerweise durch Subtrahieren des Stack-Zeigers, um die Anzahl der Elemente des Arrays zu berücksichtigen hält.
Das macht für mich Sinn. Allerdings verstehe ich nicht ganz, wie Compiler das obige Programm behandeln, da es mit G ++ (MinGW) zu funktionieren scheint, aber mit Cl, dem C ++ - Compiler von Microsoft, scheitert. Ich vermute, dass GCC Speicher auf dem Heap durch eine nicht standardmäßige Erweiterung zuweist, aber ich bin mir nicht sicher.
Außerdem ist der Compiler von Microsoft nicht dafür bekannt, dass er standardkonform ist. Daher wäre ich nicht überrascht, wenn er in der Art und Weise, wie er das obige Programm behandelt, falsch liegen könnte.
In der C99-Version des C-Standards sind Arrays mit variabler Länge zulässig. Sie sind jedoch in keiner Version von C ++ erlaubt; Sie sehen eine G ++ Erweiterung. Beachten Sie, dass der C-Compiler von Microsoft C99 nicht vollständig unterstützt; Da G ++ C99 unterstützt, ist es einfach, die VLA-Unterstützung auf C ++ als Erweiterung anzuwenden.
Wie der Compiler normalerweise VLAs implementiert, ist dasselbe wie alloca()
(außer dass er die Größe für sizeof
beibehalten muss) - der Compiler speichert den ursprünglichen Stack-Zeiger und passt ihn dann um so viele an Bytes berechnet es, dass es benötigt. Der Nachteil ist, dass der Ein- und Ausstieg der Funktion ein wenig komplizierter ist, da der Compiler den Stack-Pointer aufsetzen muss, anstatt ihn nur durch feste Konstanten anzupassen.
Es gibt absolut kein Problem mit der Subtraktion des Stapelzeigers zur Laufzeit um einen Laufzeitwert. Und so implementieren die Compiler normalerweise Arrays variabler Länge. Sie "subtrahieren" den Stack-Pointer zur Laufzeit, wenn die tatsächliche Array-Größe bereits bekannt ist. Das ist alles dazu. (Es ist nicht notwendig, Speicher auf dem Heapspeicher zuzuweisen und ich weiß nicht, was Sie im GCC vermuten ließ.).
Eine solche Funktionalität war verfügbar, lange bevor VLAs Teil der Sprache wurden. Die [Nicht-Standard] -Funktion alloca
macht genau das. Der einzige Unterschied besteht darin, dass der von alloca
zugewiesene Speicher automatisch freigegeben wird, wenn die Funktion beendet wird, während die lokalen VLAs den standardmäßigen blockbasierten Regeln für Lebensdauer folgen müssen. Letzteres ist überhaupt kein Problem, da das Nest in einer Stapel-ähnlichen Weise verschachtelt wird.
Mit anderen Worten, für einen Laufzeitwert n
die Deklaration
wird im Wesentlichen in etwas wie
übersetzt %Vor% plus einige zusätzliche Haushaltsdaten, um die Funktionalität von sizeof
etc (und natürlich die automatische Wiederherstellung des ursprünglichen Stack-Pointer-Wertes am Ende des umschließenden Blocks) zu unterstützen.
Dies ist kein legales C ++. G ++ akzeptiert Arrays variabler Länge als Erweiterung, aber VLAs sind nicht Teil des C ++ - Standards. Sie sind Teil des C99-Standards, den GCC unterstützt (ich bin mir nicht sicher, in welchem Umfang), aber MSVC nicht.
Tags und Links c c++ c++11 visual-c++ templates