Zum Inhalt springen

Empfohlene Beiträge

Geschrieben

Kann mir jemand sagen, warum eine Variable vom Typ INT bei einer Ausgabe mal den Wert 1 und dann wieder 256 hat?

Wir haben im Unterricht folgendes Bsp. geschrieben:

#include <iostream.h>

#include <conio.h>

void main() {

int anfang, ende;

cout << anfang << endl;

cout << ende;

getch();

}

Wieso gibt er 1 und 256 aus? Die Variable ist doch normalerweise nicht gesetzt.

Sobald aber die Variable global und nicht innerhalb eines Funktionsblockes gesetzt wird ist sie = 0.

Geschrieben

Also, bei mir gibt er da nicht 1 und 256 aus, sonder beides Mal -858993460, also undefinierte Werte!!!

Ich kann mir nur vorstellen dass das Dein Compiler macht. Das wenn Du einer Variablen nicht definitiv einen Wert zugewiesen hast, das er die dann bei einer Ausgabe mit bestimmten Werten besetzt.

Bine

Geschrieben

Hi,

ein Variable die du innerhalb einer Funktion deklarierst, wird nicht

mit einem Wert versehen und enthält somit zufällige Werte.....

Sobalt du diese Variable Global deklarierst wird ihr der Wert 0 zugewiesen.

Innerhalb einer Funktion ist eine zuweisung wie:

int i=0,x=0;

bestimmt nicht die schlechteste Idee ;-)

gruß Frosch03

Geschrieben

Bei C++ werden die Variablen nicht automatisch initialisiert (wie z.B. bei Visual Basic).

Daher wird irgendein Wert der gerade im Speicher steht, ausgegeben!

Du musst die Variablen daher immer selbst initialisieren

Gruss, Mugglberger

Geschrieben

Selbst wenn Variablen automatisch initialisiert werden ist dies nicht unbedingt ein guter Programmierstil. In den meisten Faellen profitieren die Leute davon wenn man Variablen mit sinnvollen Werten initialisiert ohne sich auf den Compiler zu verlassen.

Nic

Geschrieben

"Wieso gibt er 1 und 256 aus? Die Variable ist doch normalerweise nicht gesetzt."

Irgendwas muß er ja ausgeben, wenn Du eine Variable abfrägst, egal ob sie gesetzt ist oder nicht. *** VS setzt im Debug-Modus z.B. vor und nach allozierten Variablen und Objekten digitale Signaturen, um Bereichsüberschreitungen und Memory-Leaks erschnüffeln zu können. Auch diese Signaturen können dann u.U ohne Initialisierungen plötzlich drin stehen (jedenfalls häufig bei Zeigervariablen und fehlerhaftem Code). Innerhalb von Funktionen wird alles auf dem Stack abgelegt. Dieser wird jedoch pausenlos vom gesamten Thread benutzt. Da kann es auch sein, daß man mal "Müll" von vorher ausliest, wenn die Variable dort plötzlich angelegt wird.

"Sobald aber die Variable global und nicht innerhalb eines Funktionsblockes gesetzt wird ist sie = 0."

Globale Variablen werden nicht während der Programmlaufzeit und vom Programm selbst initialisiert, sondern vom Programm-Lader, der lediglich weiß, daß halt eine Variable im Programm verwendet wird und wie groß sie ist. In Wahrheit steht da aber keine Variable, sondern die Positionen der Befehle, die die Variable benutzen, welche er - nachdem er die Variable im Heap reserviert hat - mit der Adresse der Variable initialisiert. Die Variable selbst wird nicht mit Werten versehen und kann daher alles mögliche beinhalten!

An der Position wo der Variable Speicher zugewiesen wird (also noch bevor das Programm überhaupt gestartet wird!) kann also sehr wohl auch noch Müll von ehemaligen Vorprogrammen oder auch einfach vom Bios-Speichertest stehen.

Die Einzige Ausnahme sind im (Resource)Daten-Segment, welches tatsächlich Inhalte, also Initialisierungen hat.

Das ist auch der Grund, warum man statische Elemente in Klassen auch immer nochmal direkt initialisieren muß - alle Objekte der Klasse müssen da schließlich auf dieselbe Position im Speicher zugreifen. Diese Elemente werden genauso wie die globalen Variablen im rData-Segment vom Programm abgelegt, welche immer Initialisierungen beinhalten!

Geschrieben
Original geschrieben von Crush

An der Position wo der Variable Speicher zugewiesen wird (also noch bevor das Programm überhaupt gestartet wird!) kann also sehr wohl auch noch Müll von ehemaligen Vorprogrammen oder auch einfach vom Bios-Speichertest stehen.

Ich freue mich immer wieder wenn ich kompetente Antworten in diesem Forum zu sehen bekomme. Allerdings ist deine Aussage über (ich gehe mal davon aus dass du lokale Variablen meinst) den "Müll" nicht korrekt. Lokale Variablen werden auf dem Stack gespeichert und nicht auf dem Heap oder im Arbeitsspeicher. Folglich wird dieser "Müll" nicht von "ehemaligen Vorprogrammen" erzeugt (was auch gar nicht möglich ist, da Windows jedem Programm 2 GB privaten Speicher zuweist) sondern eher von der Tatsache, dass auf dem Stack noch Bytes liegen die zum eigenen Programmcode gehören. Dabei ist es egal ob es mal Variablen, Konstanten oder einfach nur Programmcode war bzw waren. Ansonsten bin ich mit deiner Erklärung weitestgehend zufrieden.

Gruß,

Danarama's Friend (war zu faul mich auszuloggen ;))

Geschrieben

Also ich weiss zwar nicht genau, wie Windows seinen Speicher handelt, aber zu sagen, ein frisch gestartetes Programm haette eine Art von jungfraeulichem Stapelspeicher, duerfte eine Illusion sein. Die Laufzeitumgebung muss eben *irgendwie* Speicher holen, und in eben diesem Stueck Speicher kann vorher der Brief an Tante Erna oder die Zahl PI gewesen und stehengeblieben sein, egal ob Heap oder Stack.

Also vernebelt doch bitte bei allen wissenswerten Details nicht das Grundprinzip von C und C++: Alles, was man nicht haendisch initialisiert, hat einen undefinierten Wert. Wem das nicht gefaellt, der muss halt Jehovah nehmen; da ist am Anfang immer ne Null drin. ;)

Und uebrigens: Seit wann ist Speichermanagement von Windows an dieser Stelle ein gueltiges Topic? ;)

Geschrieben

@Danarama

Vielleicht habe ich mich nicht so doll ausgedrückt, weil ich ja was anderes damit gar nicht sagen wollte als das was Du geschrieben hast, Ich stimme also einfach zu ca. 99% mit ein wie Du´s sagst, weil:

Auch der Stack wird nur in vorhandemem Speicher vom System reserviert - und da kann jederzeit was anderes vorher dringestanden haben - auch wenn´s schon lange her ist.

Das mit den Lokalen Variablen ist klar, die kommen meist auf dem Stack. Es sei denn der Compiler macht Fastcalls oder automatische, bzw. erzwungene Register-Optimierung oder gar Inline-Calls, dann wird nämlich alles direkt in den Prozessorregistern überreicht und der Stack außen vor gelassen (bis auf den Einsprungs-Instruction-Pointer), bzw. teils gar kein echter Funktionsaufruf gemacht - auch wenn man scheinbar (laut Source) eine Funktion "aufruft" - weil ja bei Inline-Funktionen Kopien der Funktion direkt ins Programm eingefügt werden und damit jeglicher Aufruf überflüssig wird.

Ich wollte nur etwas "technisch" aufklären, wobei Gaius´ Erklärung den Nagel direkt auf den Kopf trifft. Klingt auch irgendwie logisch, daß nirgendwo etwas Bestimmtes zu stehen hat, solange ich nicht klar sage was wo stehen soll.

@GaiusUlius

Ich schreibe natürlich alles aus meiner Windows-Sicht, weil ich die einfach am besten kenne. Dabei gehe ich einfach mal davon aus, daß halt bei X86-Prozessoren das ganze so abläuft.

Funktionsaufrufe sind aber bis heute noch nirgends standardisiert und daher kann das sehr wohl schon beim selben Betriebssystem vollkommen anders aussehen: Pascal, Basic, diverse C-Konventionen und fast jeder Sprach-Compiler braucht bei Funktionsaufrufen gerne sein eigenes Süppchen. Kommt also nicht nur drauf an wer aufruft, sondern auch was aufgerufen wird (in welcher Programmiersprache dasjenige Welche erstellt wurde).

Der Prozessor selbst allerdings trägt auch noch einen großen Teil dazu bei, weil zwar elemantar solche Abläufe ähnlich sind, aber die Stack-Verwendung ganz anders organisiert sein kann. Mit Enter- & Leave kann man ja Stacks direkt selbst aufbauen und so stört sich dann niemand mehr - davon machen aber C-Compiler relativ selten Gebrauch - höchstens bei neuen Prozessen oder Threads - das würde aber jetzt zu weit führen.

So viele Variablen spielen bei Speicheraufbau und Aufrufkonventionen eine Rolle, daß es schon fast ein Wunder ist, daß alles "irgendwie" miteinander läuft.

Geschrieben
Original geschrieben von Crush

Funktionsaufrufe sind aber bis heute noch nirgends standardisiert und daher kann das sehr wohl schon beim selben Betriebssystem vollkommen anders aussehen: Pascal, Basic, diverse C-Konventionen und fast jeder Sprach-Compiler braucht bei Funktionsaufrufen gerne sein eigenes Süppchen. Kommt also nicht nur drauf an wer aufruft, sondern auch was aufgerufen wird (in welcher Programmiersprache dasjenige Welche erstellt wurde).

Kommt drauf an, es gibt eine Menge Architekturen/Betriebssysteme bei denen "Calling-Conventions" existieren an die sich alle Compiler halten. Das ist beispielsweise bei Linux, HPPA und Sun der Fall. Waere dem nicht so, koennte man keine Fortran-Objekt Dateien mit C, C++ oder Assembler-Code linken (oder auch gcc .o-Files mit .o der Compiler der Hersteller bzw. den Systembibliotheken). Sun definiert in der Architekturbeschreibung genau, wie mit den Registerfenstern umzugehen ist (ebenso HP in den Procedure Calling Conventions). Ich gehe davon aus, dass es auch in der Microsoft-Welt was vergleichbares gibt.

Nic

Geschrieben

"Calling Conventions" gibt´s schon ... nur halt keinen Systemübergreifenden oder auch einfach einen einzelnen System-Standard! Aber es ging ja mehr darum, warum und wie Variablen initialisiert sind oder werden müssen. Und deren Inhalte sind nicht nur von den Conventions schwer abhängig.

Geschrieben

Was meinst Du mit "systemuebergreifend"? Es macht wenig Sinn, Sparc-Objektdateien mit HPPA oder Intel linken zu koennen. Betriebssystemuebergreifend (auf der gleichen Prozessorarchitektur) funktioniert das durchaus. Zwar nicht unbedingt in der Windows-Welt aber bei Unix-Systemen ist das ueblicherweise kein Problem (wenn Du unter Windows cygwin installiert hast, kannst Du beispielsweise auch Linux Dateien mit verwenden).

Nic

Geschrieben

Damit meinte ich die Variablenübergabe auf den Stack bei Funktionsaufrufen allgemein. Bei unterschiedlichem Prozessor-Code ist das nicht möglich - ist ja auch klar.

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...