Die Regeln beim Anlegen von Arrays
-
Im Buch steht:
Lokal definierte Vektoren werden erst zur Laufzeit des Programms auf dem Stack erzeugt.
Bei der Definition von Vektoren ist daher folgendes zu beachten:- Vektoren die einen größeren Speicherbereich belegen, (z.B. mehr als 1 KByte) sollten global oder static definiert werden.
- Ohne eine Initialisierung haben die Elemente eines lokalen Vektors nicht notwendigerweise einen definierten Wert.
Die Zuweisung von Werten erfolgt in der Regel in einer Schleife.Beides verstehe ich nicht: Warum sollten die Array die größer als 1 KByte sind, global sein? Weil das Programm sonst stocken würde?
Was passiert ohne Initialisierung? Können die dann doch lokal sein? Würde es dann nicht stocken? Warum erst in einer Schleife?
-
Dein Buch will dir sagen, dass Arrays - wie alle deklarierten variablen - auf dem Stack angelegt werden. Wie viel platz auf dem Stack vorhanden ist, hängt von Compiler und Betriebssystem ab. Wenn du ein Array á la
int array[ 100 ];deklarierst, so sind die Werte des Arrays einigermaßen zufällig. Es sind eben die Werte, die auf dem Stack herumliegen. Deshalb solltest du dein Array initialisieren:
int array[ 100 ] = { 0, 0, 0, /* ... */ 0 }; // oder: for( size_t i = 0; i < 100; ++i ) { array[ i ] = 0; /* oder sonstwas ;) */ }greetz, Swordfish
-
...oder einfach:
int array[ 100 ] = { 0 };
-
Mein Lieblingscompiler initialisiert dann nur das erste Element. Was sagt der Standard?
greetz, Swordfish
-
Hallo,
Der Standard sagt dazu folgendes in 8.5.1 7
If there are fewer initializers in the list than there are members in the aggregate, then each member not
explicitly initialized shall be value-initialized (8.5).Das bedeutet in diesem Fall, dass ab dem 2. Element alle Elemente mit int() (also 0) initialisiert werden sollten.
-
hm ich hab mal soeben mit visual studio 2005 getestet:
int array[ 100 ] = { };
alle sind nullund:
int array[ 100 ] = { 66 };
nur das erste 66, die nachfolgenden alle null
und:
int array[ 100 ] ; // error bei ausgabe!
aber die Antwort auf die Frage warum man global definieren muss, habe ich noch nicht bekommen oder? Ich kann mir das mit dem Stack bildlich nicht richtig vorstellen, ist es ein hardwareteil irgendwo im Chip? - wenn ich es global definiere ist es nicht auf dem stack? Wieviel bytes passt den was in Stack hinein? was passiert wenn es mehr sind?
-
OMG.
Alle (non-static) LOKALEN Variablen und alle PARAMETER landen auf dem Stack. Globale Variablen sind weder lokal noch sind es Parameter, also landen sie nicht auf dem Stack.
Der Stack ist im übrigen ganz normales RAM, bloss eben ein bestimmter Bereich der pro Thread eben "für den Stack" reserviert wird.
Verwaltet wird der mit dem Stack-Pointer.Auf den Stack kann man "oben" Sachen "drauflegen", und man kann Sachen wieder runternehmen in der Reihenfolge wie sie draufliegen. Lokale Variablen werden wenn sie angelegt werden draufgelegt, und wenn die Funktion zurückkehrt wieder runtergenummen.
Ruft die Funktion A nun aber eine andere Funktion B auf, dann bleiben die lokalen Variablen der Funktion A auf dem Stack, und die von Funktion B werden oben drauf gelegt. Der Stack wächst also immer weiter und weiter je tiefer man Funktionen verschachtelt. Und wenn er "voll" ist machts *bumm".Mit kleinen Variablen bekommt man den Stack kaum voll (ausser man verwendet Rekursion, da muss man immer aufpassen), mit sehr grossen Variablen (Arrays etc.) geht das allerdings oft schneller als man denkt. Und DAHER sollte man grosse Dinge nicht auf den Stack legen.
-
x schrieb:
aber die Antwort auf die Frage warum man global definieren muss, habe ich noch nicht bekommen oder?
Du musst Variablen überhaupt nicht global definieren. Normalerweise definiert man Variablen dort, wo sie logisch am besten passen. Für gewöhnlich bedeutet das so lokal wie möglich. Natürlich gibt es auch Ausnahmen, zB wenn man dynamische oder sehr grosse Daten hat. Dann verwendet man den Freispeicher.
x schrieb:
Ich kann mir das mit dem Stack bildlich nicht richtig vorstellen, ist es ein hardwareteil irgendwo im Chip?
Auf x86 Plattformen ist der Stack nichts weiter als stinknormaler Hauptspeicher. Er wird vom Betriebssystem einfach separat verwaltet und von der CPU mit einem separaten Registern (SS:ESP) angesprochen.
x schrieb:
wenn ich es global definiere ist es nicht auf dem stack?
Richtig. C++ kennt drei Arten von Speicher, Speicher mit statischer, automatischer und dynamischer Laufzeit. Hinter globalen Variablen versteckt sich Speicher mit statischer Laufzeit, dh dieser ist während der gesamten Laufzeit der Anwendung gültig. In Funktionen definierte Variablen sind zB automatisch (sofern nicht explizit das Schlüsselwort static verwendet wird). Ihnen wird kontextabhängig Speicher zugewiesen. Auf x86 Systemen bedeutet das, sie werden auf dem Stack untergebracht. Sie sind auch nur in dieser Funktion gültig, werden also bei der Definition erzeugt, und sind spätestens beim Verlassen des Gültigkeitsbereiches, also spätestens am Ende der Funktion Geschichte.
x schrieb:
Wieviel bytes passt den was in Stack hinein? was passiert wenn es mehr sind?
Die Grösse des Stacks ist systemabhängig, daher solltest du dir über sowas keine Sorgen machen. 100 Bytes sind jedenfalls für heutige Verhältnisse nicht wirklich viel, um sie nicht auf dem Stack unterbringen zu können. Wenn es wirklich viel werden sollte, also im hohen KB oder gar MB Bereich, dann ist der Freispeicher die richtige Wahl.