Das Array ist statisch, aber die Array-Größe ist erst zur Laufzeit bekannt. Wie ist das möglich?

9

Das beunruhigt mich schon eine Weile. Es geht um mein (mangelndes) Verständnis des Unterschieds zwischen statischer und dynamischer Speicherzuweisung. Das folgende Array ist ein normales statisches Array, das bedeutet, dass der Speicher während der Kompilierungszeit zugewiesen wird, richtig? Aber ich habe es so eingerichtet, dass der Benutzer die Array-Größe zur Laufzeit eingibt.

%Vor%

Beachten Sie, dass in diesem Programm keine Operatoren new oder delete vorhanden sind. Es funktioniert gut in Xcode 4.2 (Standard-Clang-Compiler) sowie auf dem UNIX-Server meiner Schule (GCC 4.4.5). Wie weiß der Compiler, wie viel Speicher für arr reserviert werden muss, wenn das Array zur Kompilierzeit erstellt wird? Ist das nur ein Zufall meines Compilers, gefährlicher Code, der anderen Speicher korrumpieren könnte, oder ist das echt?

    
y0ssar1an 14.01.2012, 09:49
quelle

4 Antworten

8

Dies ist eine nicht standardmäßige Erweiterung Ihrer C ++ - Compiler. Beachten Sie, dass in C im Gegensatz zu C ++ dies seit C99 offiziell unterstützt wird (d. H. Standardmandatiertes Verhalten). In C ++ wird es nicht unterstützt, da es bereits eine Lösung für das Problem gibt: Verwenden Sie std::vector anstelle des Arrays.

Nicht jedoch, dass das Array nicht ist, das die statische Speicherzuweisung verwendet (auch nicht die dynamische Speicherzuweisung), sondern die automatische Speicherzuweisung. Automatische Variablen werden automatisch am Ende der Funktion freigegeben (der Speicherbereich, in dem sie zugewiesen sind, wird als Stapel bezeichnet, da die Zuweisungen und Deallokationen darauf Stapelsemantik haben). Damit das Array die statische Speicherzuweisung verwendet, müssen Sie static vor die Definition setzen (Beachten Sie, dass Variablen im globalen oder Namespace-Bereich immer die statische Speicherzuweisung verwenden). Wenn Sie jedoch die Variable statisch machen, werden Sie feststellen, dass der Compiler keine nicht konstante Array-Größe mehr zulässt.

Beachten Sie, dass std::vector stattdessen seine Daten mit dynamischen Speicherzuweisungen speichert. Aus diesem Grund können Sie auch für statische std::vector s eine nicht konstante Größe verwenden.

    
celtschk 14.01.2012, 09:55
quelle
4

Für ein Array (oder ein beliebiges Objekt), das innerhalb einer Funktion deklariert ist, wird der Speicher beim Eintritt in die Funktion (normalerweise auf dem Stapel) zugewiesen und bei Zuweisung der Funktion wieder freigegeben. Die Tatsache, dass die Funktion in diesem Fall main ist, hat keinen Einfluss darauf.

Dies:

%Vor%

ist ein "Array variabler Länge" (VLA). Die Sache ist, C ++ unterstützt keine VLAs. C tut dies, beginnend mit dem ISO-C-Standard von 1999 (C99), aber es ist kein Merkmal, das C ++ übernommen hat.

Ihr Compiler unterstützt VLAs in C ++ als Erweiterung. Wenn Sie sie verwenden, ist Ihr Code nicht tragbar.

(Ein Problem mit VLAs ist, dass es keinen Mechanismus gibt, um einen Zuweisungsfehler zu erkennen; wenn arraySize zu groß ist, ist das Programmverhalten nicht definiert).

Für gcc erzeugt das Kompilieren mit -pedantic eine Warnung:

%Vor%     
Keith Thompson 14.01.2012 09:58
quelle
1

Der generierte Code weist Array-Size-Bytes zur Laufzeit auf dem Stack zu. Sobald die Funktion zurückkehrt, wird der Stapel abgewickelt, einschließlich "Zurückgeben" der Bytes, die ihm für das Array zugewiesen wurden.

Mit new und delete wird Speicherplatz auf dem Heap zugewiesen. Die zugewiesene Speicherlebensdauer auf dem Heap ist unabhängig von einem Funktions- oder Methodenbereich. Wenn Sie ihm in einer Funktion Speicherplatz zuweisen und die Funktion zurückgibt, ist der Speicher weiterhin zugewiesen und gültig.

    
Danra 14.01.2012 09:53
quelle
0

Es ist ein Array variabler Länge (nur in C99 und nicht in C ++ unterstützt). Es wird zur Laufzeit auf dem Stack zugeordnet.

    
Igor Oks 14.01.2012 09:52
quelle