typedefs in Strukturen, Frage zu Syntax
-
also ich als neuling kenne zeigerdeklarationen nur folgendermaßen
(ein beispiel, falls man einen zeiger auf eine variable setzen will):int var;
int *zgr;
zgr = &var;daher weiß ich nicht wirklich, was jetzt LIST* sein soll, da hier das sternchen am ende steht.
in meinem beispiel hat doch LISTZGR als wert die adresse von LIST, oder nicht?
-
das sternchen hinter dem typ zeigt an, dass ein zeiger auf den typ gemeint ist.
c ist es völlig egal, ob dutypedef LIST* LISTZGR;
oder
typedef LIST *LISTZGR;
schreibst. es ging mir darum, was das eigentlich meint. rein semantisch ist die erste form besser, da damit klar ausgedrückt wird, dass LISTZGR ein zeiger auf LIST ist.
aber wie der freundliche zwischenredner schon darlegte: bei variable sollte man das nicht machen.
-
"bei variable" heißt so viel wie man sollte
typedef a* zgr_a
statt
typedef a *zgr_a
machen, right?
Wenn ja, wieso?
(zgr_a soll ein zeiger auf die variable a sein)
-
das sind typedefs und keine variablen deklarationen.
bei typedefs benutze ich die variante mit dem stern an dem typen. bei variablen gehört der stern an die variable, auch wenn es semantisch nicht sehr glücklich ist. als erklärung dient das bsp, was "um gottes willen" anführte:
int* a,b;
a ist ein pointer auf ein int und b ist ein normales int.
-
Mapu schrieb:
"bei variable" heißt so viel wie man sollte
typedef a* zgr_a
statt
typedef a *zgr_a
machen, right?
Wenn ja, wieso?
(zgr_a soll ein zeiger auf die variable a sein)wo das *-Zeichen ist, ist dem Compiler egal. Menschen sind doof und muessen sich die Sachen merken, indem sie assozieren.
Um einen Pointer zu deklarieren muss ein *-Zeichen vor dem Bezeichnername stehen.
int *ptr, no_ptr, *ein_ander_ptr, *wieder_ein_pointer, kein_ptr;
Betrachte diese Deklaration:
int* a,b,c,d,e,f,g;
beliebter Fehler von Anfaengern ist es, das *-Zeichen mit dem Datentyp (int) zu assozieren und daraus schliessen, dass
a,b,c,d,e,f
undg
Zeiger sind. Doch nura
ist in Wirklichkeit ein Zeiger, denn das *-Zeichen steht nur vora
und nicht vor allen anderen Bezeichnern, somit sindb,c,d,e,f
undg
keine Zeiger. Aus diesem Grund gewoehnt man sich an, das *-Zeichen neben dem Bezeichnername zu schreiben, so:int *a,b,c,d,e,f,g;
damit assozieren wir (dumme) Menschen schneller, dass das *-Zeichen nur auf
a
wirkt, also ist es schneller (fuer Anfaenger) zu sehen, dass nura
ein Zeiger ist.Mit dem typedef ist es aehnlich, es geht nur um die visuelle Assoziation, damit man schneller sieht, um was es sich handelt.
-
ah danke schön, verstanden
eine nebensache, wollte keinen anderen thread aufmachen:
wie wichtig sind denn so verkettete listen eigentlich? habe ein listing gesehen, bei dem 5 buchstaben eingegeben, in strukturen gespeichert und mit hilfe von verketteter liste dann sortiert werden. ist ganz schön aufwändig, meiner meinung nach (war nur ein demo beispiel für die anwendung von verk. listen). gehören diese listen also einfach zu einem bestimmten aspekt von c oder zu, ich sag mal, absolut notwendigen grundwissen?
-
Mapu schrieb:
ah danke schön, verstanden
eine nebensache, wollte keinen anderen thread aufmachen:
wie wichtig sind denn so verkettete listen eigentlich? habe ein listing gesehen, bei dem 5 buchstaben eingegeben, in strukturen gespeichert und mit hilfe von verketteter liste dann sortiert werden. ist ganz schön aufwändig, meiner meinung nach (war nur ein demo beispiel für die anwendung von verk. listen). gehören diese listen also einfach zu einem bestimmten aspekt von c oder zu, ich sag mal, absolut notwendigen grundwissen?
Listen und Arrays sind die meistgenutzten Datenstrukturen schlecht hin. Und das nicht nur in C sondern allgemein beim Programmieren.
Bäume und Hashmaps sind auch noch ziemlich wichtig, aber Arrays und Listen sind das was du am meisten antreffen wirst.
Gibt natürlich noch viel mehr Datenstrukturen, aber die oben genannten tauchen auch schon in recht einfachen Programmen auf (Bäume nicht mal unbedingt, Hashmaps schon eher, wobei man hier auch auf einen Baum ausweichen könnte).
-
Der Vorteil von Listen ist zum einen, daß Arrays im Gegensatz zu Listen einen zusammenhängenden Speicherbereich brauchen.
Ein anderer ist, daß du eine Liste, die entsprechenden Funktionen vorausgesetzt, besser bearbeiten kannst. Um zB ein Listenelement an x-ter Stelle einzufügen, mußt du nur ein neues Element erstellen und 2 Pointer verschieben (wofür du auch eine entsprechende Funktion haben solltest. Bei doppelt verketteten Listen natürlich 4 Pointer...). Bei Arrays müßtest du den Speicherbereich vergrößern, die Elemente ab x jeweils um eins nach hinten verschieben und dann kannst du dein neues Element erst einfügen.
Listen können zudem Elemente verschiedener Datentypen beinhalten, bei einem Array müssen alle Elemente vom gleichen Typ sein.
Nachteile der Liste sind der zusätzliche Speicherverbrauch für die Pointer und ein langsamerer Zugriff auf die Elemente, die weiter hinten in der Liste sind.
Bei den in Tutorials aufgeführten Beispielen ist der Sinn meistens schwer zu erkennen und es wird zu oft auch nicht näher drauf eingegangen.
-
Nagila Hawa schrieb:
Bei den in Tutorials aufgeführten Beispielen ist der Sinn meistens schwer zu erkennen und es wird zu oft auch nicht näher drauf eingegangen.
Das war mein Problem
Das gewählte Beispiel war zwar relativ sinnvoll, bzw. eine Demo für etwas Sinnvolles, aber die Materie, wie Du sie mir erklärt hast, erschließt sich mir auch jetzt erst. Ich habe heute ca. 2 Std. gebraucht, um ein listing durchzugehen, welches, wie oben beschrieben, nur 5 Buchstaben sortiert und hing dabei an Definitionen von Zeiger vs. Variable vs. Element vs. Strukturzeiger fest - weil einfach alles nur angerissen wurde in der Erklärung. Ich werd mich aber noch durchackern, danke jedenfallsDa fällt mir aber nochwas am Programm auf:
Die Struktur lautetstruct list { int ch; /* Verwende int zum Aufnehmen der Zeichen. */ struct list *next_el; /* Zeiger auf nächstes Listenelement. */ };
Weiter unten wird der head-Zeiger folgendermaßen deklariert/initialisiert(?!):
LISTZGR first = NULL; /* Head-Zeiger */
Initialisiere/deklariere (?!) ich demnach einen Zeiger auf eine neue Struktur einfach mittels
struct name_der_struktur *name_des_zeigers
? Durch den typedef-Befehl, LISTZGR auf LIST zu setzen, wird es also einfach einfacher?
-
Ich finde den LISTZGR unnötig.
Ein neues Element forderst du wie üblich mit malloc() an.
list *pNeuesElement; pNeuesElement = malloc(sizeof(list));
Um jetzt dieses neue Element z.B. hinten anzufügen, mußt du das letzte Element suchen (üblicherweise mit "NULL" im "*next"-pointer), den Pointer "*pNeuesElement" dem pointer "*next" dieses Elements zuweisen und den "*next"-pointer vom neuen Element auf "NULL" setzen.
Dafür schreibst du dir einfach einmal neue Funktionen, benennst sie entsprechend (z.B. "append" für anfügen, "insert" für einfügen, "delete" zum Entfernen) und du brauchst dir keine großen Gedanken mehr darüber zu machen.