Wieso geht's mal und mal nicht?

Hallo, hier mal wieder eine „typische Anfängerfrage“?!

Wieso funktioniert der folgende Quelltextauszug bei
‚Bloodshed Dev-C++ Version 4‘ und bei ‚VC++ 6.0‘ verursacht
er in der Zeile der Felddeklaration (***) nur die Fehlermeldung „Konstanter Ausdruck erwartet“???
Ist das nicht eigentlich alles C++?

Quelltext-Auszug:
{
int Zaehler, i;
cout >Zaehler;
int Werte[Zaehler]; // (***)

…}

Ich will’s ja nur mal verstehen :expressionless:

Vielen Dank, den Wissenden!
Thomas

Hi,

Quelltext-Auszug:
{
int Zaehler, i;
cout >Zaehler;
int Werte[Zaehler]; // (***)

…}

Also meines Erachtens duerfte das nicht gehen.
Es gibt verschiedene Arten, Speicher fuer Variablen zu allozieren. Die beiden auf die es hier ankommt sind Allokation auf dem Stack (das willst Du machen) und auf dem Heap (das muesstest Du machen).
Der Stack ist ein fester (!) Speicherbereich der die Anweisungen in einer Funktion und Speicher fuer Variablen enthaelt. Das Layout des Stacks wird vom Compiler bei der Kompilation ein fuer alle mal fest gelegt. Da laesst sich zur Laufzeit nichts mehr aendern (z.B. ein Array beliebiger Groesse allozieren, wie oben). Der Gueltigkeitsbereich von Variablen auf dem Stack wird bei C++ durch den Scope (alles zwischen zwei geschweiften Klammern {…}) festgelegt.
Vom Heap kann man mit new jederzeit soviel Speicher anfordern, wie man will. Dieser Speicher wird nicht automatisch verwaltet wie der Stack. Einmal angeforderter Speicher bleibt so lange unangetastet, bis er explizit wieder freigegeben wird oder bis das Programm beendet wird. Man muss sich also darum kuemmern, das man die Adressen dieses Bereichs behaelt (z.B. in Pointern, die ihrerseits jeweils irgendwo im Stack alloziert sind).

Gruss

Thorsten

HAllo Thomas

Wieso funktioniert der folgende Quelltextauszug bei
‚Bloodshed Dev-C++ Version 4‘ und bei ‚VC++ 6.0‘ verursacht
er in der Zeile der Felddeklaration (***) nur die
Fehlermeldung „Konstanter Ausdruck erwartet“???
Ist das nicht eigentlich alles C++?

Quelltext-Auszug:
{
int Zaehler, i;
cout >Zaehler;
int Werte[Zaehler]; // (***)

…}

Der „Bloodshed Dev-C++“ scheint hier eindeutig einen Fehler zu machen.
Die Anweisung:
int Werte[Zaehler];
besagt, dass der Compiler den Speicherplatz für ein Array aus „int“ mit „Zaehler“ Einträgen reservieren soll. Nun ist aber der Wert von „Zaehler“ zur Compilierzeit noch nicht bekannt, und der „VC++“-Compiler reklamiert zu recht, dass er an dieser Stellen einen Konstante erwartet. Ansonsten müsste der Compiler platz für ein Array der Grösse „int Werte[MAX_INT]“ reservieren, bei 16-Bit int sind das 64KByte (MAX_INT ist (2^15)-1 = 32767, wegen dem Vorzeichen), bei 32-Bit int sind das dann aber 4 * 2^31 = 8 GByte und das ist dann das doppelte von dem virtuellen Adressraum welcher ein Pentium überhaupt ansteuern kann.

MfG Peter(TOO)

Hi Thomas :smile:))

Eigentlich hat VC++ völlig Recht, wenn es dir einen Fehler meldet. Bei der Definition eines Arrays muss die Array-Größe dem Compiler beim Compilieren bekannt sein. Daher sind Variablen nach ANSI-C/C++ nicht zulässig.

Einige Compiler erzeugen jedoch Code, der den obigen Fall trotzdem handhaben kann. Zur Laufzeit wird dann auf dem Stack (nicht auf dem Heap) ein entsprechend großer Speicherbereich angelegt. Diesen musst du auch nicht wieder freigeben, da dies bei Verlassen der Funktion automatisch passiert. (Nur Heap-Speicher muss explizit durch den Reservierer freigegeben werden).

Der Bloodshed Dev-C++, wie übrigens auch der GNU-C-Compiler, bieten hier also eine Erweiterung des Standards. In VC++ kannst du das allerdings auch per Hand machen:

int *Werte= (int*)_alloca[sizeof(int)*Zaehler];

Dazu musst du allerdings die Header-Datei einbinden.

cu Stefan.

Vielen Dank
Hallo Stefan,

vielen Dank (auch den anderen beiden). Der erste Teil:

Eigentlich hat VC++ völlig Recht, wenn es dir einen Fehler
meldet. Bei der Definition eines Arrays muss die Array-Größe
dem Compiler beim Compilieren bekannt sein. Daher sind
Variablen nach ANSI-C/C++ nicht zulässig.

war mir nämlich so geläufig. Du kannst Dir sicher vorstellen, wie erstaunt ich war, als mir jemand beim Dev-C++ etwas völlig anderes zeigte.
Zumal, wenn man sich nach einigen Jahren erst wieder so richtig an C/C++ gewöhnen muß (…gewöhnen: Ich glaube, ich muß für mich auch bald mal die Begriffe „Stack“ und „Heap“ klären. „Stack“ ist mir noch teilweise was in Erinnerung :expressionless: ).

Vielen Dank auch noch für den Tip:

int *Werte= (int*)_alloca[sizeof(int)*Zaehler];

Tschau Thomas

Hi Thomas :smile:

Ein Stack wird zum Anlegen lokaler Variablen benutzt. Du brauchst dich um seine Verwaltung nicht zu kümmern, denn lokale Variablen werden automatisch zerstört, wenn man die Funktion verlässt, in der sie definiert wurden. In C/C++ gibt es für solche Objekte eigentlich das Schlüsselwort auto , was aber stets weggelassen wird.

Ein Heap ist ebenfalls ein Speicherbereich zum Anlegen von Objekten. Jedoch werden hier die Objekte nicht automatisch (wie beim Stack) angelegt und zerstört, sondern das musst du mit new/delete bzw. malloc/free selber machen. Der Vorteil des Heaps ist, dass dort reservierte Speicherbereiche auch nach Beendigung der Funktion, in der sie definiert wurden, weiter existieren. Daher ist es wichtig, dass du als Programmierer diese reservierten Speicherbereiche auch wieder schön freigibst.

Du kannst dir das in etwa so vorstellen: Einer Anwendung (einem Prozess) steht ein gewisser Speicherplatz zur Verfügung. Dieser unterteilt sich in folgende Bereiche:

(1) einen Bereich für den auzuführenden Code selbst,
(2) einen Bereich für alle verwendeten Konstanten
(3) einen Bereich für alle globalen und statischen Variablen
(4) einen Stack
(5) und einen Heap.

(1) bis (3) haben eine fest definierte Größe. Der Stack (4) wächst von unten nach oben, der Heap (5) wächst von oben nach unten. Wenn die beiden zusammentreffen, gibt’s einen „out of memory error“. Also solltest du den Heap immer schön sauber halten :smile:))

In Wirklichkeit ist es ein wenig komplizierter, weil eine Prozess mehrere Threads enthalten kann, die sich dann alle Bereiche bis auf den Stack teilen. Aber das würde jetzt zu weit führen …

cu Stefan.

Hallo Stefan,

noch einmal vielen Dank, mit einer so schnellen Antwort hätte ich nicht gerechnet :smile:))))

malloc/free kenne ich noch von früher, bloß der Zusammenhang zum Begriff „heap“ war mir nicht mehr geläufig. Oder es hieß früher anders (wenn ich mich recht erinnere, dann sprachen wir damals einfach vom Speicher :expressionless: )

Auf jeden Fall gefällt mir wer-weiss-was immer besser. Da kann man ja richtig schlau werden (schleim…).

Wie lange machst Du das mit C/C++ denn eigentlich schon?
Ggf. müßte ich bestimmt noch mal auf Deine Hilfe zurückkommen, oder hast Du 'ne eigene Homepage mit vielen Informationen zu C/C++ !?

Tschau, Thomas

Hi Thomas :smile:

Wie lange machst Du das mit C/C++ denn eigentlich schon?

Programmieren tue ich seit meinem 12-ten Lebensjahr, also jetzt 21 Jahre lang. C habe ich so mit 16 Jahren kennengelernt. Da war ich in den Schulferien an der Uni zum Programmierenlernen, das nannte sich damals Begabtenförderung, mein Mathe-Lehrer hatte mich dahin vermittelt. Danach hat mich C nicht mehr losgelassen … C++ mache ich jetzt seit etwa 6 Jahren …

Ggf. müßte ich bestimmt noch mal auf Deine Hilfe zurückkommen,

Kein Problem, das bisschen, das ich weiß, teile ich gerne mit anderen Programmierern :smile:

oder hast Du 'ne eigene Homepage mit vielen Informationen zu
C/C++ !?

Nee, dafür habe ich keine Zeit, sorry :smile:

cu Stefan.