Array of Structs
-
printf gegen cout ersetzen hilft da evtl., gibt zumindest einiges an Typsicherheit. Ein häufiger Fehler der vorkommen kann ist, dass beim char-Array die Nullterminierung vergessen wurde. std::strings können da Abhilfe schaffen, die kümmern sich da automatisch selber drum.
-
Mein Programm sieht vereinfacht (obwohl, so viel einfacher sieht es gar nicht aus) so aus:
/* main.h */ #include <windows.h> #include <cstdio> typedef int schwachsinnig; struct abstruct { int a; int b; }; extern abstruct *abtest; void abthread(void); schwachsinnig einefunktion(void);/* lala.cpp */ #include "main.h" schwachsinnig einefunktion(void) { return 12; }/* main.cpp */ #include "main.h" abstruct *abtest; void abthread(void) { while(true) { abtest->a = (int) einefunktion(); } } int main(int argc, char **argv) { CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE) abthread, NULL, NULL, NULL); while(true) { printf("\r \r%02d", abtest->a); // std::cout bringt auch nichts :'-( Sleep(1000); } return 0; }
-
abtest ist ein Zeiger, den du weder initialisierst noch ihm eine Adresse zuweist. Dadurch zeigt er auf irgendwas im Speicher, sodass das Verhalten undefiniert ist, wenn du ihn dereferenzierst, was du mit abtest->a aber machst.
Loesung: Initialisiere den Zeiger mit der Adresse eines abstruct-Objekts oder alloziere Speicher auf dem Heap fuer ein abstruct-Objekt, auf das der Zeiger dann zeigt.
-
Und für alle, die Informatik noch nicht studiert haben?
-
Ich meine, kannst du mir das an dem Beispiel von oben erklären?
-
Ist das richtig?
/* main.cpp */ #include "main.h" abstruct *abtest = new abstruct; // ...Das funktioniert so :0
-
Mit abstruct *abtest deklarierst du einen sog. Zeiger auf ein abstruct-Objekt. Ein Zeiger ist erstmal nur ein Verweis - eine Referenz - auf eine Speicherstelle. D.h. an der Stelle, wo der Zeiger hinzeigt, sollten gueltige Daten des Typs, auf den dein Zeiger verweist, liegen. In deinem Fall sollte an der Stelle ein Objekt einer abstruct-Struktur liegen. Leider weist du nirgendwo in deinem Programm dem Zeiger abtest eine Speicheradresse zu. Soweit ich weiss, bekommen global deklarierte Zeiger den Defaultwert NULL (nicht zu verwechseln mit der mathematischen 0), was bedeutet, dass dein Zeiger nirgendwo hin zeigt. Lokal deklarierte Zeiger bekommen keinen Defaultwert, wenn du sie nicht initialisierst, d.h. sie zeigen "irgendwo" hin (abhaengig davon, was gerade im Speicher fuer den Zeiger stand).
Wenn du nun auf das Objekt, auf das dein Zeiger verweist, zugreifen willst, musst du einen * vor den Namen des Zeigers schreiben. Das nennt man "Dereferenzieren". Du musst also, um auf die Elementvariable a zuzugreifen, den Zeiger abtest dereferenzieren und dann mit dem Punktoperator a auswaehlen: (*abtest).a. Die Klammern sind noetig, da der Punktoperator eine hoehere Prioritaet hat als der *-Operator. Genau das tust du zweimal in deinem Programm, denn abtest->a ist nur eine Kurzform fuer (*abtest).a.
Leider zeigt abtest - wie gesagt - auf nichts, sodass es kracht, wenn du versuchst, ihn zu dereferenzieren.
Vielleicht ist es in deinem Fall auch ueberfluessig, einen Zeiger zu verwenden. Entferne den Stern in abstruct *abtest und mache aus abtest->a den Code abtest.a, dann sollte es auch funktionieren.
-
Spacken schrieb:
Ist das richtig?
/* main.cpp */ #include "main.h" abstruct *abtest = new abstruct; // ...Das funktioniert so :0
Ja, das ist fast richtig. Auf diese Weise laesst du deinen Zeiger auf ein abstruct-Objekt zeigen, das du mit Hilfe des new-Operators auf dem Heap erstellt hast. Da du diesen Speicher selbststaendig dynamisch "alloziert" hast, bist du auch dafuer verantwortlich, dass dieser Speicher wieder freigegeben wird.
Dies kannst du mitdelete abtest;erledigen; aber erst, wenn du den Speicher nicht mehr benoetigst.
-
GyroGearloose schrieb:
Spacken schrieb:
Ist das richtig?
/* main.cpp */ #include "main.h" abstruct *abtest = new abstruct; // ...Das funktioniert so :0
Ja, das ist fast richtig. Auf diese Weise laesst du deinen Zeiger auf ein abstruct-Objekt zeigen, das du mit Hilfe des new-Operators auf dem Heap erstellt hast. Da du diesen Speicher selbststaendig dynamisch "alloziert" hast, bist du auch dafuer verantwortlich, dass dieser Speicher wieder freigegeben wird.
Dies kannst du mitdelete abtest;erledigen; aber erst, wenn du den Speicher nicht mehr benoetigst.
Irgendwie gibt printf, bevor "einefunktion" das erste Mal ausgeführt wird, eine merkwürdige Zahl (-842150451) aus... sollte das nicht zu dem Zeitpunkt 0 sein?

-
Nein, das ist der gleiche Sachverhalt wie mit der zufaelligen Speicheradresse des Zeigers. Wenn du a nicht initialisierst, dann steht dort ein zufaelliger Wert, der beim Erzeugen der Variable gerade dort im Speicher steht (in deinem Fall -842150451). Ich glaube, dass nur global deklarierte Zeiger/Variablen/Objekte einen Default-Wert (i.d.R. 0) - sofern moeglich - erhalten. Sicherer und vor allem besserer Stil ist aber immer, alles zu initialisieren.
-
Achso... ich glaube, dass ich das jetzt soweit verstanden habe. Danke für deine Zeit!
-
GyroGearloose schrieb:
Ich glaube, dass nur global deklarierte Zeiger/Variablen/Objekte einen Default-Wert (i.d.R. 0) - sofern moeglich - erhalten. Sicherer und vor allem besserer Stil ist aber immer, alles zu initialisieren.
Globale und statische Variablen (Speicherklassen
extern,static) sowie Instanzen von Klassen mit Standardkonstruktor werden auch automatisch mit ihrem Defaultwert initialisiert.Edit: Wobei erstere je nachdem getrennt von der Deklaration definiert werden müssen.
-
// ... struct abstruct { int a; int b; }; // ... abstruct einefunktion(void) { abstruct abReturn = { 0, 0 }; // ... return abReturn; } // ... int main(int argc, char **argv) { // ... if(einefunktion() != { 0, 0 }) // <--- Funktionierende Alternative? return 1; // ... }(Frage s. "Funktionierende Alternative" ^^)
-
Also ich möchte den Rückgabewert nicht speichern sondern nur schnell vergleichen...
-
nein, mit {0, 0} alleine kann der nix anfangen.
bool operator==(abstruct const& a, abstruct const& b) { return a.a == b.a && a.b == b.b; } bool operator!=(abstruct const& a, abstruct const& b) { return !(a == b); } struct abstruct { abstruct(int a, int b) : a(a), b(b) {} u.s.w. } if(einefunktion() == abstruct(0, 0)) ...so in etwa ungetestet.
-
Wenn du schön mit temporären Variablen arbeiten willst, kannst du in deiner Struktur einen Konstruktor einbauen.