Ich bin in der Stimmung zu erklären dies ohne blutige Gedächtnis- la Ihre Details (glauben Sie mir, sie erhalten sehr gory, wenn VLAs verwendet werden; Einzelheiten finden Sie in der Antwort von @ Ulfalizer.
So ursprünglich in C89, war es zwingend notwendig, alle Variablen zu Beginn eines Blockes, wie dies zu erklären:
{
int a = 1;
a++;
/* ... */
}
bedeutet dies direkt eine sehr wichtige Sache: einen Block == ein unveränderlicher Satz von Variablendeklarationen.
C99 hat dies geändert. Darin können Sie Variablen in jedem Teil des Blocks deklarieren, aber Deklarationsanweisungen unterscheiden sich immer noch von regulären Anweisungen.
Um dies zu verstehen, können Sie sich vorstellen, dass alle Variablendeklarationen implizit an den Anfang des Blocks verschoben werden, wo sie deklariert und für alle Anweisungen, die ihnen vorausgehen, nicht verfügbar sind.
Das ist einfach weil der eine Block == eine Reihe von Deklarationen Regel noch gilt.
Deshalb können Sie nicht "über eine Deklaration springen". Die deklarierte Variable würde immer noch existieren.
Das Problem ist die Initialisierung. Es wird nirgends "bewegt". Also, technisch gesehen, für Ihren Fall, die folgenden Programme als gleichwertig angesehen werden könnten:
goto later;
int a = 100;
later:
printf("%d", a);
und
int a;
goto later;
a = 100;
later:
printf("%d", a);
Wie Sie sehen können, die Erklärung ist immer noch da, was ausgelassen wird, ist die Initialisierung.
Der Grund, warum dies nicht mit VLAs funktioniert, ist, dass sie anders sind.Kurz gesagt, ist es, weil dies gilt:
int size = 7;
int test[size];
Die Erklärungen von VLAs werden, im Gegensatz zu allen anderen Erklärungen, verhalten sich anders in verschiedenen Teilen der Blöcke, in dem sie deklariert ist. Tatsächlich kann ein VLA völlig unterschiedliche Speicherlayouts haben, abhängig davon, wo es deklariert ist. Du kannst es einfach nicht außerhalb des Ortes bewegen, über den du gerade gesprungen bist.
Sie können fragen, "in Ordnung, dann warum es nicht so machen, dass die Deklaration von der goto
unberührt bleiben würde"? Nun, Sie würden immer noch Fälle wie diese:
goto later;
int size = 7;
int test[size];
later:
Was erwarten Sie eigentlich, dies zu tun ..
So, das Verbot des Sprungs über VLA Erklärungen gibt es für einen Grund - es ist am meisten? logische Entscheidung, um Fälle wie die obigen zu behandeln, indem man sie einfach ganz verbietet.
@ Mints97 Ah, also, wenn Statements ihre eigenen Blöcke auch ohne zusammengesetzte Anweisungen haben? Ich nehme an das ist die antwort dann :) schade ich kann keine kommentare – MinecraftShamrock
was meinst du damit? was haben die if-aussagen damit zu tun? Und Blöcke und zusammengesetzte Anweisungen sind mehr oder weniger gleich, IIRC – Mints97
@ Mints97 Ich meine, bedingt deklarierte Variablen werden nicht an den Anfang der gesamten Funktion verschoben, sondern nur bis zum Anfang des bedingten "Blocks", in dem sie existieren? Eine if-Anweisung ohne zusammengesetzte Aussage würde also auch einen solchen Block darstellen. Ist mein Verständnis richtig? – MinecraftShamrock