als ich habe vollgenden Programcode bekommen und verstehe ihn nicht. ich
mus leider zugeben das ich nicht der Beste Programmierer bin, hoffe aber
das ihr mir helfen könnt es zu verstehen.
Die erste Zeile steht in meiner .c Datei der rest in der .h. für mich
sah im ersten moment zeile 1 aus wie ein Funktionsaufruf. Scheint aber
keiner zu sein. Sondern irgend ein "Sonderding" bei strukturen.
Ich danke euch für eure Hilfe
Jürgen schrieb:> Die erste Zeile steht in meiner .c Datei der rest in der .h. für mich> sah im ersten moment zeile 1 aus wie ein Funktionsaufruf. Scheint aber> keiner zu sein.
Doch, es ist einer. Schlag mal in deinem C-Buch das Kapitel "Funktions-
zeiger" bzw. "Functon Pointers" auf.
> Sondern irgend ein "Sonderding" bei strukturen.
Mit Strukturen hat das nur insofern etwas zu tun, dass der Funktionszei-
ger name2 Element einer Struktur (structname) ist. Er könnte aber auch
eine eigenständige Variable sein.
Ich verstehe es leider noch nicht.
Also was ich denke / hoffentlich verstehe ist:
1) ich lege eine struktur mit drei "Variablen" an.
name1, name2, name3.
1
consttstructname*name4=NULL;
so habe ich das im Code gefunden.
2) in name3 kann ich ein char abspeichern.
3) name1 ist ein zeiger auf eine Variable
was verbirgt sich jetzt hinter name2 ?
mit
1
name4->name2(name4,name7);
schreibe ich in meine Instanz name4 an die Stelle name2 was? Ich
übergebe nur zwei Zeiger? Name5 und name 6
Jürgen schrieb:> was verbirgt sich jetzt hinter name2 ?
Ein Zeiger auf eine Funktion.
> mit name4->name2(name4,name7); schreibe ich in meine Instanz name4 an> die Stelle name2 was?
Gar nichts. Du rufst die Funktion auf.
> Ich übergebe nur zwei Zeiger?
Ja.
Jürgen schrieb:> was verbirgt sich jetzt hinter name2 ?
Ein Zeiger auf eine Funktion.
In name2 steht die Adresse einer Funktion. Die kann man aufrufen.
>> mit
1
name4->name2(name4,name7);
schreibe ich in meine Instanz
> name4 an die Stelle name2 was? Ich übergebe nur zwei Zeiger? Name5 und> name 6
du bist völlig falsch.
name4 ist ein Zeiger auf ein structur Objekt.
Dieses Strukturobjekt hat ein paar Member. Einen undefinierten (da void)
Pointer, der überallhin zeigen kann, solange es nur Daten sind. Einen
uchar. Und eben auch einen Zeiger auf eine Funktion.
Und genauso, wie man auf den uchar zugreift:
name4->name3 = 'a';
j = name4->name3;
um ihm etwas zuzuweisen bzw den dort abgespeicherten Wert zu holen,
genauso spezifiziert man dann eben mit
name4->name2
erst mal den Funktionspointer. So, was macht man damit? Man kann ihm zb
die Adresse einer Funktion zuweisen
void meine_Funktion( const struct structname * name5, char *name6 )
{
...
}
name4->name2 = meine_Funktion;
oder aber man kann die Funktion auch aufrufen
name4->name2( );
und da die Funktion 2 Argumente haben will, einen Pointer auf ein const
structname und einen char Pointer, gibt man die dann eben beim Aufruf
an.
Hättest du meine_Funktion direkt aufgerufen, hättest du das auch müssen
meine_Funktion( iregendwas, irgendwas_anderes );
beim indirekten AUfruf über einen Funktionszeiger ist das auch nicht
anders
name4->name2( irgendwas, irgendwas_anderes );
Wie oben schon gesagt: Dein C Buch sollte das ganze noch wesentlich
ausführlicher beschreiben.
Da kann man auch schon mal durcheinander kommen, wenn alles "name"x
heißt. Darum ist es guter Stil, die Namen so zu wählen, dass man gleich
die Bedeutung/Funktion erkennt.
... schrieb:> Da kann man auch schon mal durcheinander kommen, wenn alles "name"x> heißt. Darum ist es guter Stil, die Namen so zu wählen, dass man gleich> die Bedeutung/Funktion erkennt.
Da der Code nicht von Jürgen selbst stammt, vermute ich, dass da
ursprünglich andere Namen standen, aus denen die Funktion der einzelnen
Typen, Variablen und Elemente deutlicher hervorgegangen ist.
Yalu X. schrieb:> ... schrieb:>> Da kann man auch schon mal durcheinander kommen, wenn alles "name"x>> heißt. Darum ist es guter Stil, die Namen so zu wählen, dass man gleich>> die Bedeutung/Funktion erkennt.>> Da der Code nicht von Jürgen selbst stammt, vermute ich, dass da> ursprünglich andere Namen standen, aus denen die Funktion der einzelnen> Typen, Variablen und Elemente deutlicher hervorgegangen ist.
Das hoffe ich mal ganz stark.
Und auch an den Fragesteller die Aufforderung:
Bitte ersetzte solche vernünftige Namen nicht durch welche, die du dir
gerade ausgedacht hast. Das ist nämlich auch beim Schreiben einer
Antwort mehr als lästig, wenn man ständig rauf runter scrollen muss, nur
um sich zu vergewissern ob man jetzt den richtigen Member genommen hat
oder nicht. Mit einigermassen aussagekräftigen Variablennamen merkt man
sich die leicht und selbst wenn man mal einen Tippfehler macht, ist das
nicht so schlimm. Aber wenn das alles name1, name2, name5 test1, test2,
test3, ... heißt, ist eine Verwechslung wahrscheinlich und auch nicht so
leicht erkennbar.
Jürgen schrieb:> ist das so richtig??
Nein, durch die erneute Namensänderungen ist jetzt fast alles falsch,
was man falsch machen kann.
Wenn du die Namen unbedingt ändern musst, mach es wenigstens mit
Search/Replace und schau, ob der Compiler das Ergebnis noch ohne
Fehlermeldungen und Warnungen annimmt.
Yalu X. schrieb:> Nein, durch die erneute Namensänderungen ist jetzt fast alles falsch,>> was man falsch machen kann.
das ist bitter, ich versuche mal die sachen runterzuladen.
Dein Beispiel ist reichlich sinnlos. Es bringt auch nichts, wenn du
extrem lange Namen für ein Beispiel wählst. Wenn dir gar nichts anderes
einfällt, dann benutze für ein Beispiel die Situation "Auto" oder
"Haustiere". Das funktioniert meistens recht gut.
1
// Datentyp für den Funktionspointer erzeugen
2
sructHund;
3
tpydefvoid(*Aktion)(structHund*dog);
4
5
// Ein Hund hat einen Namen und als Funktionspointer verknuepft
6
// eine Funktion die aufgerufen werden kann, wenn der Hund jemanden
7
// begruessen soll
8
structHund
9
{
10
char*Name;
11
AktionBegruessung;
12
}
13
14
//
15
// Hier sind die möglichen Begruessungsaktionen. Jeweils als
16
// Funktion implementiert
17
//
18
voidwedeln(structHund*dog)
19
{
20
printf("Hi, ich bin %s und zur Begruessung wedele ich mit dem Schwanz\n",dog->Name);
21
}
22
23
voidhochSpringen(structHund*dog)
24
{
25
printf("Hi, ich bin %s und zur Begruessung springe ich an dir hoch\n"dog->Name);
26
}
27
28
//
29
// Und dann gibt es noch 2 Hunde
30
// Sie haben jeweils unterschiedliche Namen und ihre Begruessungsaktionen
31
// sind verschiedene
32
//
33
structHundFifi={"Fifi",wedeln};
34
structHundBrutus={"Brutus",hochSpringen);
35
36
37
intmain()
38
{
39
// Beide Hunde sollen mal eine Begruessung machen
40
41
// das kann jetzt so aussehen ...
42
wedeln(&Fifi);
43
hochSpringen(&Brutus);
44
// .. aber dazu hat der Programmierer das Wissen benutzt, das
45
// Fifi mit dem Schwanz wedelt und Brutus hochspringt. Diese
46
// 'Verknuepfung' des Verhaltens ist an dieser Stelle direkt
47
// im Programmcode enthalten.
48
49
// genau das wollen wir aber manchmal nicht. Fifi soll selber
50
// wissen, dass er mit dem Schwanz zu wedeln hat. Das weiß er auch.
51
// Er weiß es in Form seines Funktionspointers, der zur Funktion
52
// führt, die die Begruessung macht.
53
// Also ....
54
Fifi.Begruessung(&Fifi);
55
Brutus.Begruessung(&Brutus);
56
57
//
58
// Soweit so gut. Interessant wird das ganze nämlich dann, wenn
59
// im Code gar nicht mehr bekannt ist, um welchen Hund es sich
60
// handelt.
61
// Existiert nur ein Pointer auf irgendeinen Hund ....
62
structHund*Koeter;
63
64
// ... und zeigt dieser Pointer 'zufällig' auf Fifi ...
65
Koeter=&Fifi;
66
67
// ... dann wird ueber den Funktionspointer die jeweils
68
// richtige Funktion ....
69
Koeter->Begruessung(Koeter);
70
71
// ... aufgerufen
72
73
// und natuerlich auch, wenn dieser 'irgendein Hund' der andere
74
// Hund ist.
75
Koeter=&Brutus;
76
Koeter->Begruessung(Koeter);
77
78
// Man beachte: Der Funktionsaufruf ist in beiden Fällen syntaktisch
79
// derselbe!
80
// Koeter->Begruessung( Koeter );
81
// und trotzdem wird je nachdem um welchen Hund es sich handelt, die
82
// jeweils richtige Funktion aufgerufen. In der jeweiligen Objektinstanz
83
// selber ist in Form eines Funktionspointers abgelegt, welche das ist.
84
// Die Daten selber steuern die Programmausführung und nicht mehr
85
// der Programmierer hat zur Entwicklungszeit festgelegt, welche Funktion
86
// konkret aufzurufen ist.
87
// D.h. er hat es schon festgelegt. So ein Programm kann ja auch nicht
Tatsächlich ist noch eine frage aufgekommen.
Was ich überhaupt nicht verstehe ist folgendes:
1
typedefstructMember{
2
ucharname;
3
ucharvisits;
4
}tMember;
5
6
externconsttMembermembernumber;
Also wenn ich mehrere Member anlege, dtelle ich mir vor das für jeden
Member Speicherplatz für den Namen und die Anzahl der Besuche festgelegt
wird.
Was mach aber die Mitgliedsnummer? was ist der unterschied zu:
[c]
typedef struct Member {
uchar name;
uchar visits;
int membernumber
} tMember;
membernumber ist eine Variable vom Typ tMember.
Mit
1
typedefstructMember{
2
ucharname;
3
ucharvisits;
4
}tMember;
wurde der Typ tMember definiert.
1
consttMembermembernumber;
definiert eine Variable namens membernumber vom Typ tMember, also hat
membernumber die Member name und visits.
Das Keyword extern besagt in dem Falle nur, dass membernumber in einer
anderen Datei definiert wurde und in dieser Datei auch benutzt wird.
DAnke. Den namen muss ich dan wirklich noch ändern.
So habe die (vorerst) letzte Frage:
1
externconsttMember*constlist[];
hier wird ein array erzeugt, in dem alle Member stehen? Auch
membernumber ? Kann ich tMember erzeugen die nicht in diesem array
stehen?
Hups, jetzt sind es doch Fragen geworden.
Jürgen schrieb:> DAnke. Den namen muss ich dan wirklich noch ändern.> So habe die (vorerst) letzte Frage:>>
1
>externconsttMember*constlist[];
2
>
>> hier wird ein array erzeugt, in dem alle Member stehen?
Nein.
Lies die Deklaration. In diesem Array stehen keine Member, sondern in
diesem Array sind Pointer enthalten, die auf Objekte vom Typ tMember
zeigen können.
(Ich lass die const erst mal weg um dich nicht zu verwirren)
1
2
list list ist
3
list[] list ist ein Array
4
* list[] list ist ein Array von Pointern
5
tMember * list[] list ist ein Array von Pointern, wobei
6
jeder Pointer auf ein tMember zeigen kann
7
extern tMember * list[] list ist ein Array von Pointern, wobei
8
jeder Pointer auf ein tMember zeigen kann
9
und dieses Array wird nicht hier erzeugt,
10
sondern existiert irgendwo anders im
11
Program
Immer schon mit der rechts/links Regel beim Variablennamen anfangen und
sich nach aussen durcharbeiten.
> Auch> membernumber ?
Wenn da irgendjemand mal die Adresse von membernumber ins Array eintägt
dann steht der drinnen. Wenn nicht, dann nicht.
Technisch möglich ist es. Denn in list werden die Speicheradressen von
tMember Objekten abgelegt. membernumber ist ein tMember Objekt. Also
kann man seine Speicheradresse in diesem Array ablegen.
> Kann ich tMember erzeugen die nicht in diesem array> stehen?
In dem Array sind überhaupt keine Member enthalten, sondern nur Pointer
auf tMember Objekte. Wo auch immer die erzeugt wurden und welcher Code
auch immer diese ins Array eingetragen hat.
Analogie:
Dieses Array entspricht dem Schlagwortkatalog in einer Bibliothek. Die
Bücher stehen irgendwo in den heiligen Hallen in einem Regal. IM Katalog
gibt es für jedes Buch ein Kärtchen, auf dem steht: "Kernighan&Ritchi
findet sich in Gang A, Regal 5, 6. Buch von links". Das ist das, was
dein list Array machen kann: Einen Verweis zu geben, wo das tatsächliche
Buch zu finden ist (und das du dir ausborgen solltest). Aber im
Schlagwortkatalog sind NICHT die Bücher selber eingelagert.
... das (annähernd) Selbe.
AVerr schrieb:> Mittypedef struct Member {>> uchar name;>> uchar visits;>> } tMember;>>>> wurde der Typ tMember definiert.const tMember membernumber;>>>> definiert eine Variable namens membernumber vom Typ tMember, also hat>> membernumber die Member name und visits.>> Das Keyword extern besagt in dem Falle nur, dass membernumber in einer>> anderen Datei definiert wurde und in dieser Datei auch benutzt wird.
das passt aber hiermit nicht zusammen. oder?
Jürgen schrieb:> Karl Heinz Buchegger schrieb:>>> Du solltest den Hinweis im Bücherei-Beispiel ernst nehmen. Ich hab nicht>>>>>> ohne Grund dieses Buch ausgewählt.>>>> Sorry, verstehe ich nicht.
hat sich erledigt. Halbschlaf ;-)
Jürgen schrieb:> ... das (annähernd) Selbe.
Fast.
Das eine mal hat die Struktur einen Namen (und kann damit auch an
anderen Stellen verwendet werden), das andere mal hat die Struktur
keinen Namen. Da werden dann einfach 2 Variablen von diesem Typ erzeugt
und das wars. Die STruktur kann abgesehen von diesen 2 Variablen
nirgends anders mehr benutzt werden - weil sie ja keinen Namen hat mit
dem man sie ansprechen könnte.
> das passt aber hiermit nicht zusammen. oder?
Das hat damit überhaupt nichts zu tun. Völlig andere Baustelle.
Bücherei:
Kernighan&Richtie
Programmieren in C
Jürgen schrieb:> Wie völlig andere Baustelle? Das ist doch das Selbe, oder nicht?Jürgen schrieb:> Karl Heinz Buchegger schrieb:>> Bücherei:>> Kernighan&Richtie>> Programmieren in C> liegt hier neben mir
In dem Buch gibt es bestimmt einen Abschnitt über Structs und Typen (
Stichwort typedef ).
Ich kann mir schon denken, wo dein Problem liegt.
Wenn du so ein Struct siehst:
1
struct{
2
intdata;
3
}structVar
dann ist es auch richtig, dass structVar eine Variable ist, die diese
Struktur erfüllt, du also auf das int structVar.data zugreifen kannst.
structVar hat in dem Fall einen konkreten Speicherbereich, in dem data
gespeichert ist.
Im Falle
1
typedefstruct{
2
intdata;
3
}tStruct;
ist tStruct nur der Name eines neuen Datentypen. Es bekommt keinen
eigenen Speicher zugewiesen.
Du kannst nun aber Variablen dieses Typen erstellen, z.B. mit
1
tStructstructVar;
Diese structVar ist analog zu der oben, liegt im Speicher, du kannst
structVar.data verändern.
Nun verstehst du hoffentlich auch, warum es eine komplett andere
Baustelle ist ... aufgrund des Gebrauchs von typedef.
Jürgen schrieb:> Wie völlig andere Baustelle? Das ist doch das Selbe, oder nicht?
WAS ist dasselbe?
Bitte wirf mir nicht Satzfetzen vor und ich darf mir dann raussuchen,
wovon du eigentlich sprichst.
Die einzige Gemeinsamkeit besteht darin, dass eine Struktur vereinbart
wird. Das wars aber dann auch schon.
Jetzt kann ich mir aussuchen, ob sich deine Frage über die Gemeinsamkeit
auf
* den Strukturnamen
* den typedef
* oder den extern
bezieht. Gottlob lautet in den letzten 2 Fällen die Antwort: andere
Baustelle.
so ich habe versuch das hunde Beispiel zu compilieren um es besser zu
verstehen.
Leider geht es nicht und ich verstehe nicht warum.
typedef und struct ist einmal falsch geschrieben.
Ich bekomme drei Fehlermeldungen:
1
voidwedeln(structHund*dog)
two or more data types in declaration of wedeln
Syntax error before dog
Martin G schrieb:> schon wieder der schiss mit dem Namen. ich bin Jürgen.
Wir sind hier nicht besonders entzückt über Leute, die sich als mehrere
unterschiedliche Leute ausgeben müssen.
Gewöhn' Dir das ab. Dringend.
Das macht ja gar keinen Sinn. Das eine bin ich das andere mein Bruder.
Ist doch eh anonym.
Sieht zwar doof aus, das gebe ich zu, aber ich bin ich :-) und mein
bruder mein Bruder
Martin G schrieb:> Das macht ja gar keinen Sinn.
Doch, das hat sehr wohl einen Sinn, wir wollen hier schon wissen, mit
welcher Instanz anonymer Benutzer wir es zu tun haben.
Andernfalls könnte ja auch jeder nicht angemeldete Benutzer von der
Forensoftware als "Gast" bezeichnet werden ... dann haben wir viele
Threads, in denen sich "Gast" mit "Gast" und "Gast" unterhält. Wenn dann
noch "Gast", "Gast" und "Gast" dazukommen, wird es fast schon gemütlich.
Das habe ich nicht gemeint. Es macht aus meiner Sicht keinen Sinn. Es
gibt ca 10M Jürgens in Deutschland. Wenn ich meine Identität verstecken
wollte hätte ich mich einfach Jupp genannt.
Aber sei es wie es ist. Ich bin ich und versuche immer oben zu gucken
wer "eingeloggt" ist, ich oder mein Bruder.
Ich habe versucht mein Problem zu lösen. Habe leider noch kein
ergebniss. kann mir da jemand helfen?
> Aber hier fangen schon die Probleme an. Das akzeptiert der compiler> schon nicht:
1
structhund
2
{
3
char*name;
4
intgewicht;
5
}Michaelshund;
6
7
structhundJuergenshund={"Fifi",15};
8
structhundSabineshund={"Ali",11};
9
10
Michaelshund.name="Bello";
11
Michaelshund.gewicht=13;
Die beiden Zuweisungen an die Strukturelemente von "Michaelshund" sind
außerhalb einer Funktion nicht zulässig, im Gegensatz zu den
Initialisierungen von Juergens- und Sabineshund.
> und was auch nicht funktioniert ist:
1
typedefvoid(*Aktion)(structhund*dog);
2
3
structhund
4
{
5
char*name;
6
intgewicht;
7
AktionBegruessung;
8
};
9
10
structhundJuergenshund={"Fifi",15,wedeln};
11
structhundSabineshund={"Ali",11,wedeln};
12
13
voidwedeln(structhund*dog)
14
{
15
printf("Hi, ich bin %s und zur Begruessung wedele ich mit dem Schwanz\n",dog->Name);
16
}
Zum Zeitpunkt der Initialisierung von Juergens- und Sabineshund ist die
Funktion "wedeln" nicht bekannt. Du musst diese Funktion dem Compiler
vor der Initialisierung bekanntmachen, entweder mit einem Prototypen
(einer Deklaration) oder durch das Verschieben der Definition der
Funktion vor die Initialisierungen.
Beides sind Dinge, die in einem anständigen C-Buch beschrieben werden.
Den allfälligen Literaturhinweis will ich deswegen nicht weglassen:
Brian Kernighan & Dennis Ritchie, "Programmieren in C", 2. Ausgabe,
Hanser-Verlag.
Aber auch die Fehlermeldungen des C-Compilers weisen auf diese
Probleme hin, die gilt es zu lesen und zu verstehen.
Jürgen schrieb:> Syntax error before Aktion
Das ist nicht die ganze Meldung.
Ich glaube zwar, in welcher Zeile das ist - aber es ist dein Job das zu
sagen.
Sollen hier alle rumraten, nur weil du zu faul bist, eine vernünftige
Fehlerbeschreibung zu machen?
Jürgen schrieb:> Karl Heinz Buchegger schrieb:>> Bücherei:>>>> Kernighan&Richtie>>>> Programmieren in C>> liegt hier neben mir
Leg es doch mal vor dich, dann kannst du es lesen!
Jürgen schrieb:> es geht um diese Zeile:> Aktion Begruessung;
nein, oder dein Quelltext ist nicht komplett.
Bzw. sollte noch eine Fehlermeldung vorher kommen.
Dann bekomme ich als Fehlermeldung:
t.cpp: In function ‘void wedeln(hund*)’:
t.cpp:15: error: ‘struct hund’ has no member named ‘Name’
t.cpp: At global scope:
t.cpp:18: warning: deprecated conversion from string constant to ‘char*’
t.cpp:19: warning: deprecated conversion from string constant to ‘char*’
(wenn ich es als C++ kompiliere) bzw.:
t.c:4: warning: ‘struct hund’ declared inside parameter list
t.c:4: warning: its scope is only this definition or declaration, which
is probably not what you want
t.c: In function ‘wedeln’:
t.c:15: error: ‘struct hund’ has no member named ‘Name’
t.c: At top level:
t.c:18: warning: initialization from incompatible pointer type
t.c:19: warning: initialization from incompatible pointer type
als C.
Martin G schrieb:> so ich habe versuch das hunde Beispiel zu compilieren um es besser zu> verstehen.> Leider geht es nicht und ich verstehe nicht warum.
Weil ich das Beispiel direkt hier im Editor eingetippt habe und mir
dabei natürlich ein paar Tippfehler unterlaufen sind.
Für jemanden, der sein C zumindest soweit versteht, dass er sich in der
Lage fühlt mit Funktionspointern rumzumachen, sollten die aber kein
Problem sein.
> Ich bekomme drei Fehlermeldungen:>>
1
>voidwedeln(structHund*dog)
2
>
> two or more data types in declaration of wedeln> Syntax error before dog
Hier ....
1
// Ein Hund hat einen Namen und als Funktionspointer verknuepft
2
// eine Funktion die aufgerufen werden kann, wenn der Hund jemanden
3
// begruessen soll
4
structHund
5
{
6
char*Name;
7
AktionBegruessung;
8
}<-------------------------------------------
9
10
//
11
// Hier sind die möglichen Begruessungsaktionen. Jeweils als
12
// Funktion implementiert
13
//
... fehlt ein ';'
Hier ....
>
1
>structHundBrutus={"Brutus",hochSpringen);
2
>
> syntax error before )
.... hab ich irrtümlich die falsche Klammer benutzt. ) anstelle von }
Karl Heinz Buchegger schrieb:> Weil ich das Beispiel direkt hier im Editor eingetippt habe und mir> dabei natürlich ein paar Tippfehler unterlaufen sind.>> Für jemanden, der sein C zumindest soweit versteht, dass er sich in der> Lage fühlt mit Funktionspointern rumzumachen, sollten die aber kein> Problem sein.
Nicht falsch verstehen. Ich bin dir ultra dankbar.
Jürgen schrieb:> Karl Heinz Buchegger schrieb:>> Weil ich das Beispiel direkt hier im Editor eingetippt habe und mir>> dabei natürlich ein paar Tippfehler unterlaufen sind.>>>> Für jemanden, der sein C zumindest soweit versteht, dass er sich in der>> Lage fühlt mit Funktionspointern rumzumachen, sollten die aber kein>> Problem sein.>> Nicht falsch verstehen. Ich bin dir ultra dankbar.
OK. Dann war das wohl etwas zu subtil.
Nochmal Klartext: Du bist noch nicht soweit mit Funktionspointern
rumzumachen. Mach deine Übungen in deinem Buch, arbeite die Kapitel
durch, wenn dort Übungen angegeben sind, dann mach die, erfinde für dich
Aufgaben. Lerne die Fehlermeldungen deines Compilers zu lesen. Lerne
typische Fehlermeldungen und auch, dass sich die Meldung nicht unbedingt
auf die gemeldete Zeile beziehen muss, sondern auch davor sein kann (und
nur verschleppt wurde). Lerne wann das der Fall ist und auch wie es dazu
kommt, dass ein Compiler beschwert, dass zb scheinbar eine Funktion 2
Returntypen hat.
Und in ein paar Monaten bist du dann soweit, dass du dir den Kopf über
Funktionspointer zerbrechen kannst.
Zu schnell vorzugehen bringt auch nichts. Ehrgeiz: ja. Aber falscher
Ehrgeiz ist kontraproduktiv.