Inhaltsverzeichnis

Alle Kapitel aufklappen
Alle Kapitel zuklappen
Materialien zum Buch
23
Vorwort
25
Vorwort des Gutachters
29
1 Einstieg in C
31
1.1 Übersicht zu C
31
1.2 Der ANSI-C-Standard
33
1.2.1 Welcher C-Standard wird in diesem Buch verwendet?
35
1.2.2 Der Vorteil des ANSI-C-Standards
36
1.3 Der POSIX-Standard
36
1.4 Vor- und Nachteile der Programmiersprache C
37
1.5 C in diesem Buch
39
1.6 Was benötigen Sie für C?
39
1.6.1 Texteditor
39
1.6.2 Compiler
40
1.6.3 All-in-one – die Entwicklungsumgebung
40
1.7 Welcher Compiler und welches Betriebssystem?
41
1.8 Unterschiede zwischen Windows und Linux
42
1.9 Eine Programmierumgebung einrichten – Code::Blocks für Windows
42
1.9.1 Die IDE installieren
43
1.9.2 Den Compiler installieren
46
1.9.3 Ein einfaches C-Projekt mit Code::Blocks anlegen und kompilieren
49
1.10 Eine Programmierumgebung einrichten – Nano/GCC für Linux
51
2 Eine günstige Programmierplattform – der Raspberry Pi
53
2.1 Was genau ist der Raspberry Pi?
53
2.1.1 Die Hardware des Raspberry Pi
54
2.1.2 Welche Betriebssysteme gibt es für den Raspberry Pi?
56
2.2 Installation eines Linux-Betriebssystems am Beispiel von Raspbian
57
2.2.1 Was genau ist Buster?
57
2.2.2 Raspbian aus dem Internet herunterladen
59
2.2.3 Raspbian installieren
60
2.2.4 Raspbian mit der Grundkonfiguration starten
63
2.2.5 Wie oft benötigen Sie Updates und wie gehen Sie vor?
64
2.3 Die Konfiguration des Raspberry Pi im Detail
66
2.4 Das Tool raspi-config
66
2.4.1 Das Tool raspi-config im Detail
67
3 Das erste Programm
73
3.1 Was leistet der Editor?
74
3.2 Was leistet der Compiler?
74
3.3 Was sind Include-Dateien und wozu benötigt man sie?
75
3.4 Das erste Programm – die Ausgabe eines Textes in der Konsole
75
3.5 Das Hallo-Welt-Programm im Detail
76
3.6 Wie kompiliert man ein Programm und führt es anschließend aus?
79
4 Grundlagen
81
4.1 Symbole
81
4.1.1 Bezeichner
81
4.1.2 Schlüsselwörter
82
4.1.3 Literale
82
4.1.4 Einfache Begrenzer
84
4.1.5 Kommentare
85
4.2 Zeichensätze
88
4.2.1 Basis-Zeichensatz
88
4.2.2 Ausführungszeichensatz (Steuerzeichen)
89
4.2.3 Trigraph-Zeichen
92
4.3 Strings
93
4.4 Das Einführungsbeispiel mit Strings
94
5 Basisdatentypen
95
5.1 Was ist ein Byte und wie werden Zahlen in C gespeichert?
95
5.2 Was ist eine Variable und was ist ein Variablentyp?
96
5.3 Was ist ein Operand?
97
5.4 Was ist ein Parameter?
97
5.5 Wie speichert ein Prozessor Variablen, Parameter und Operanden?
97
5.6 Was sind Speicheradressen und warum sind sie wichtig für C?
97
5.7 Deklaration und Definition von Variablen
98
5.8 Array-Datentypen (Datenfelder)
99
5.9 Standard-Datentypen
100
5.9.1 Der Datentyp »int« (Integer), Standardgröße 2 Bytes
100
5.9.2 Verwendung des Datentyps »int«
102
5.9.3 Der Datentyp »long«, Standardgröße 4 Byte
105
5.9.4 Der Datentyp »long long«, Standardgröße 8 Byte
106
5.9.5 Der Datentyp »short«, Größe 2 Byte
106
5.10 Ganzzahlige Typen mit vorgegebener Breite – <stdint.h>
107
5.10.1 <inttypes.h> (C99)
109
5.11 Die Gleitpunkttypen »float« und »double«, Größe 4 oder 8 Byte
110
5.11.1 Gleitpunkttypen im Detail
112
5.11.2 »float« im Detail
113
5.11.3 »double« im Detail
113
5.11.4 long double
114
5.11.5 Einiges zu n-stelliger Genauigkeit
114
5.11.6 Numerische Gleitpunktprobleme
116
5.12 Komplexe Gleitpunkttypen – <complex.h>
118
5.13 Der Datentyp »char«, Standardgröße 1 Byte
120
5.14 Nationale contra internationale Zeichensätze
126
5.14.1 Der Breitzeichen-Typ »wchar_t«, Größe 2 Byte
128
5.14.2 Multibyte-Zeichen, Größe 2, 4 oder 8 Byte
129
5.15 Boolesche Werte – <stdbool.h>
129
5.16 Der Unterschied zwischen vorzeichenlosen und vorzeichenbehafteten Zahlen
131
5.17 Limits für Ganzzahl- und Gleitpunktdatentypen
133
5.18 Der Typ »void«
136
5.19 Numerische Konstanten
137
5.19.1 Ganzzahlkonstanten
137
5.19.2 Gleitpunktkonstanten
138
5.19.3 Zeichenkonstanten
138
5.19.4 Stringliterale (Stringkonstanten)
138
5.20 Umwandlungsvorgaben für formatierte Ein-/Ausgabe
139
6 Formatierte Ein-/Ausgabe mit »scanf()« und »printf()«
147
6.1 Formatierte Eingabe mit »scanf()«
147
6.1.1 Der Adressoperator »&«
149
6.1.2 Probleme und deren Behandlung mit »scanf()«
151
6.1.3 Überprüfen auf das richtige Format
154
6.1.4 Zusammenfassung zu »scanf()«
156
6.2 Formatierte Ausgabe mit »printf()«
157
7 Operatoren
161
7.1 Was sind Operatoren und wozu benötigt man sie in C?
161
7.2 Arithmetische Operatoren
162
7.2.1 Dividieren von Ganzzahlen
164
7.3 Erweiterte Darstellung arithmetischer Operatoren
165
7.4 Inkrement- und Dekrement-Operatoren
167
7.5 Bit-Operatoren
168
7.5.1 Bitweises UND
169
7.5.2 Bitweises ODER
171
7.5.3 Bitweises XOR
172
7.5.4 Bitweises Komplement
173
7.5.5 Linksverschiebung
173
7.5.6 Rechtsverschiebung
175
7.5.7 Rezept für Fortgeschrittene
175
7.6 Makros für logische Operatoren und Bit-Operatoren – <iso646.h>
177
7.7 Der »sizeof«-Operator
178
7.7.1 C versus C++
179
8 Typumwandlung
181
8.1 Automatische implizite Datentypumwandlung durch den C-Compiler
181
8.1.1 Implizites »char« nach »int«
182
8.1.2 Implizites »float« nach »double«
182
8.1.3 Implizite Umwandlung in einen komplexen Gleitpunkttyp
182
8.1.4 Übliche arithmetische Datentypumwandlung
183
8.2 Wozu benötigt man das benutzerdefinierte explizite Typecasting?
186
8.3 Explizite Datentypumwandlung mit Typecasting an Beispielen
186
9 Kontrollstrukturen
189
9.1 Verzweigungen mit der »if«-Bedingung
190
9.1.1 Anweisungsblöcke
190
9.2 Die Verzweigung mit »else if«
194
9.3 Die Verzweigung mit »else«
196
9.4 Der !-Operator (logischer NOT-Operator)
200
9.5 Logisches UND (&&) – logisches ODER (||)
202
9.6 Der Bedingungsoperator »?:«
205
9.7 Fallunterscheidung: die »switch«-Verzweigung
207
9.7.1 default
210
9.8 Die »while«-Schleife
212
9.8.1 Endlosschleifen mit »while«
214
9.8.2 Fehlervermeidung bei »while«-Schleifen
215
9.9 Die »do while«-Schleife
216
9.10 Die »for«-Schleife
221
9.10.1 Einsatzmöglichkeiten der »for«-Schleife
224
9.11 Kontrollierter Ausstieg aus Schleifen mit »break«
229
9.11.1 continue
229
9.11.2 break
230
9.12 Direkte Sprünge mit »goto« – und warum man sie nicht verwenden sollte
231
9.13 Einige Anmerkungen zum Notationsstil
232
9.13.1 K&R-Stil
233
9.13.2 Whitesmith-Stil
233
9.13.3 Allman-Stil
233
9.13.4 GNU EMACS-Stil
233
9.13.5 Der Stil des Autors (K&R-like)
233
9.14 Einige Anmerkungen zu einem guten Programmierstil
234
10 Funktionen
235
10.1 Was sind Funktionen?
235
10.2 Wozu dienen Funktionen?
236
10.3 Definition von Funktionen
236
10.4 Funktionsaufruf
237
10.5 Funktionsdeklaration
238
10.6 Lokale Variablen
241
10.7 Globale Variablen
243
10.8 Statische Variablen
245
10.9 Schlüsselwörter für Variablen – Speicherklassen
246
10.9.1 auto
246
10.9.2 extern
247
10.9.3 register
247
10.9.4 static
247
10.10 Typ-Qualifizierer
247
10.10.1 volatile
247
10.10.2 const
248
10.11 Geltungsbereich von Variablen
248
10.12 Speicherklassen-Spezifizierer für Funktionen
250
10.12.1 extern
250
10.12.2 static
250
10.12.3 volatile
250
10.13 Datenaustausch zwischen Funktionen
250
10.14 Wertübergabe an Funktionen (Call-by-Value)
252
10.15 Der Rückgabewert von Funktionen
256
10.16 Die Hauptfunktion »main()«
258
10.17 Was bedeutet der Rückgabewert beim Beenden eines Programms?
260
10.17.1 Programmende auswerten
261
10.18 Funktionen der Laufzeitbibliothek
264
10.19 Getrenntes Kompilieren von Quelldateien
264
10.20 Rekursive Funktionen (Rekursion)
267
10.20.1 Exkurs: Stack
267
10.20.2 Rekursionen und der Stack
268
10.20.3 Fakultät
273
10.20.4 Fibonacci-Zahlen
274
10.20.5 Größter gemeinsamer Teiler (GGT)
275
10.21 »inline«-Funktionen
280
11 Präprozessor-Direktiven
283
11.1 Mit »#include« Dateien einbinden
284
11.2 Wichtige vordefinierte Headerdateien für C
285
11.3 Makros und Konstanten – »#define«
287
11.3.1 Symbolische Konstanten mit »#define«
287
11.3.2 Makros mit »#define«
292
11.4 Bedingte Kompilierung mit »#ifdef«
296
11.5 Vordefinierte Präprozessor-Direktiven (ANSI C)
301
11.6 Einen Makroparameter durch einen String ersetzen
304
11.7 »#undef« – Makronamen wieder aufheben
305
11.8 Fehlermeldungen ausgeben mit »#error«
306
11.9 »#pragma« (gilt nur für Windows)
307
12 Arrays
309
12.1 Arrays deklarieren
309
12.2 Initialisierung und Zugriff auf Arrays
311
12.2.1 Gültigkeitsbereich von Arrays
316
12.3 Arrays vergleichen
318
12.4 Anzahl der Elemente eines Arrays ermitteln
320
12.5 Übergabe von Arrays an Funktionen
321
12.6 Arrays aus Funktionen zurückgeben
324
12.7 Programmbeispiel zu Arrays
325
12.8 Array-Werte über die Tastatur einlesen
328
12.9 Mehrdimensionale Arrays
329
12.9.1 Mehrdimensionale Arrays initialisieren
330
12.9.2 Übergabe von zwei- bzw. mehrdimensionalen Arrays an Funktionen
343
12.10 Arrays in eine Tabellenkalkulation einlesen (CSV-Dateien)
345
12.11 Strings/Zeichenketten (»char«-Array)
346
12.11.1 Vom String zur Binärzahl
350
12.12 Einlesen von Strings
353
12.13 Die Standard-Bibliothek <string.h>
356
12.13.1 »strcat()« – Strings aneinanderhängen
356
12.13.2 »strchr()« – ein Zeichen im String suchen
357
12.13.3 »strcmp()« – Strings vergleichen
358
12.13.4 »strcpy()« – einen String kopieren
359
12.13.5 »strcspn()« – einen Teilstring ermitteln
360
12.13.6 »strlen()« – Länge eines Strings ermitteln
361
12.13.7 »strncat()« – String mit n Zeichen aneinanderhängen
362
12.13.8 »strncmp()« – n Zeichen von zwei Strings miteinander vergleichen
363
12.13.9 »strncpy()« – String mit n Zeichen kopieren
363
12.13.10 »strpbrk()« – nach dem Auftreten bestimmter Zeichen suchen
364
12.13.11 »strrchr()« – das letzte Auftreten eines bestimmten Zeichens im String suchen
365
12.13.12 »strspn()« – das erste Auftreten eines Zeichens, das nicht vorkommt
365
12.13.13 »strstr()« – einen String nach dem Auftreten eines Teilstrings durchsuchen
366
12.13.14 »strtok()« – einen String anhand bestimmter Zeichen zerlegen
367
13 Zeiger (Pointer)
369
13.1 Der Unterschied zwischen einer normalen Variablen und einem Zeiger
369
13.2 Zeiger deklarieren
370
13.3 Zeiger initialisieren
371
13.3.1 Speichergröße von Zeigern
383
13.4 Zeigerarithmetik
385
13.5 Zeiger, die auf andere Zeiger verweisen
386
13.5.1 Subtraktion zweier Zeiger
387
13.6 Typensicherung bei der Dereferenzierung
389
13.7 Zeiger als Funktionsparameter (Call-by-Reference)
389
13.7.1 Zeiger als Rückgabewert
393
13.8 Array und Zeiger
396
13.9 Zeiger auf Strings
403
13.9.1 Zeiger auf konstante Objekte (Read-only-Zeiger)
404
13.10 Zeiger auf Zeiger und Stringtabellen
405
13.10.1 Stringtabellen
407
13.11 Zeiger auf Funktionen
414
13.12 void-Zeiger
420
13.13 Äquivalenz zwischen Zeigern und Arrays
423
13.14 Der »restrict«-Zeiger
426
14 Kommandozeilenargumente
429
14.1 Argumente an die Hauptfunktion übergeben
430
14.2 Argumente aus der Kommandozeile auswerten
435
15 Dynamische Speicherverwaltung
441
15.1 Das Speicherkonzept
442
15.1.1 Code-Speicher
442
15.1.2 Daten-Speicher
443
15.1.3 Stack-Speicher
443
15.1.4 Heap-Speicher
443
15.2 Speicherallokation mit »malloc()«
444
15.3 Das NULL-Mysterium
447
15.3.1 NULL für Fortgeschrittene
447
15.3.2 Was jetzt – NULL, 0 oder \0 …?
449
15.3.3 Zusammengefasst
450
15.4 Speicherreservierung und ihre Probleme
450
15.5 »free()« – Speicher wieder freigeben
452
15.5.1 Einige ergänzende Dinge zur Freispeicherverwaltung
455
15.5.2 Prozessinterne Freispeicherverwaltung
457
15.6 Dynamische Arrays
460
15.7 Speicher dynamisch reservieren mit »realloc()« und »calloc()«
464
15.8 Speicher vom Stack anfordern mit »alloca()« (nicht ANSI C)
468
15.9 Ergänzende Anmerkungen zu »free()«
468
15.10 Zweidimensionale dynamische Arrays
469
15.11 Was muss man tun, wenn die Speicherallokation fehlschlägt?
472
15.11.1 Speicheranforderung reduzieren
473
15.11.2 Speicheranforderungen aufteilen
474
15.11.3 Einen Puffer konstanter Größe verwenden
476
15.11.4 Vor der Allokation auf eine Festplatte zwischenspeichern
476
15.11.5 Nur so viel Speicher anfordern wie nötig
476
16 Strukturen
479
16.1 Benutzerdefinierte Typendefinitionen mit »typedef«
479
16.2 Was ist ein strukturierter Datentyp und wozu benötigt man ihn in C?
480
16.3 Strukturen mit »typedef struct« deklarieren
480
16.4 Initialisierung und Zugriff auf Strukturen
482
16.5 Strukturen als Wertübergabe an eine Funktion benutzen
491
16.6 Strukturen als Rückgabewert einer Funktion benutzen
493
16.7 Strukturen miteinander vergleichen
496
16.8 Arrays von Strukturen erstellen
497
16.9 Strukturen in Strukturen (Nested Structures)
504
16.10 Weitere spezielle Datentypen
514
16.10.1 Unions
516
16.10.2 Der Aufzählungstyp »enum«
521
16.10.3 Weitere Typdefinitionen mit »typedef«
524
16.11 Attribute von Strukturen verändern
525
16.12 Bitfelder
529
16.13 Das »offsetof«-Makro
536
17 Ein-/Ausgabe-Funktionen
539
17.1 Was ist eine Datei aus Sicht der Programmiersprache C?
539
17.2 Formatierte und unformatierte Ein-/Ausgabe
540
17.3 Höhere Ein-/Ausgabe-Funktionen mit <stdio.h>
540
17.3.1 Eine Datei mit »fopen« öffnen
542
17.3.2 Zeichenweise lesen und schreiben – »getchar()« und »putchar()«
548
17.3.3 Zeichenweise lesen und schreiben – »putc()«/»fputc()« und »getc()«/»fgetc()«
553
17.3.4 Eine geöffnete Datei mit »fclose()« wieder schließen (Wichtig!)
559
17.3.5 Formatierte Ein-/Ausgaben mit »fprintf()« und »fscanf()«
563
17.4 Streams (Ein-/Ausgabe-Datenströme)
568
17.4.1 Was unterscheidet einen Stream von einer Datei?
568
17.4.2 Standard-Steams in C
568
17.4.3 Fehlerbehandlung von Streams – »feof()«, »ferror()« und »clearerr()«
571
17.4.4 Gelesene Zeichen in die Eingabe zurückschieben – »ungetc()«
573
17.4.5 Den Tastaturpuffer leeren – »fflush()«
575
17.4.6 Einen Stream positionieren – »fseek()«, »rewind()« und »ftell()«
576
17.4.7 Einen Stream positionieren – »fsetpos()«, »fgetpos()«
581
17.4.8 Zeilenweise Ein-/Ausgabe in Streams
583
17.5 Spezielle Ein-/Ausgabe-Funktionen für Streams
597
17.5.1 Blockweise lesen und schreiben – »fread()« und »fwrite()«
597
17.5.2 Eine Datei erneut öffnen – »freopen()«
608
17.5.3 Eine Datei löschen oder umbenennen – »remove()« und »rename()«
609
17.5.4 Pufferung einstellen – »setbuf()« und »setvbuf()«
612
17.5.5 Temporäre Dateien erzeugen – »tmpfile()« und »tmpnam()«
619
17.5.6 Fehler bei der Ein-/Ausgabe abfangen und behandeln
624
17.5.7 Formatiert in einen String schreiben und formatiert aus einem String lesen – »sscanf()« und »sprintf()«
628
17.5.8 Ein fortgeschrittenes Thema
634
17.6 Low-Level-Datei-I/O-Funktionen (nicht ANSI C)
643
17.6.1 Dateien öffnen mit »open()«
643
17.6.2 Dateien schließen mit »close()«
651
17.6.3 Datei erzeugen – »creat()«
652
17.6.4 Schreiben und lesen – »write()« und »read()«
652
17.6.5 Den File-Deskriptor mit »lseek()« positionieren
663
17.6.6 Einen File-Deskriptor von einem Stream mit »fileno()« ableiten
664
17.6.7 Stream von File-Deskriptor mit »fdopen()« ableiten
665
17.6.8 Gerätedateien unter Linux – Zugriff auf Maus und Framebuffer
667
18 Attribute von Dateien und das Arbeiten mit Verzeichnissen (nicht ANSI C)
673
18.1 Die Attribute einer Datei mit »stat()« ermitteln
673
18.1.1 »stat()« – »st_mode«
674
18.1.2 »stat()« – »st_size«
680
18.1.3 »stat()« – »st_atime«, »st_mtime« und »st_ctime«
682
18.1.4 »stat()« – »st_gid« und »st_uid«
686
18.1.5 »stat()« – »st_nlink«, »st_ino«
687
18.1.6 »stat()« – »st_dev«, »st_rdev«
688
18.2 Prüfen des Zugriffsrechts mit »access()«
691
18.3 Verzeichnisfunktionen
693
18.3.1 Verzeichnis erstellen, löschen und wechseln mit »mkdir()«, »rmdir« und »chdir«
693
18.3.2 In das Arbeitsverzeichnis wechseln mit »getcwd()«
699
18.3.3 Verzeichnisse öffnen, lesen und schließen – »opendir()«, »readdir()« und »closedir()«
701
19 Arbeiten mit variabel langen Argumentlisten – <stdarg.h>
707
19.1 Was ist eine Ellipse und wie werden mit ihr Parameter übergeben?
707
19.2 Wie kann man mit <stdarg.h> die Parameterliste abfragen?
708
19.3 Makros in <stdarg.h> – »va_list«, »va_arg«, »va_start« und »va_end«
708
19.4 Die Argumentliste am Anfang oder Ende kennzeichnen
709
19.5 »vprintf()«, »vsprintf()«, »vfsprintf()« und »vsnsprintf()«
714
19.6 Variadic Makros – __VA_ARGS__
719
20 Zeitroutinen
723
20.1 Die Headerdatei <time.h>
723
20.1.1 Konstanten in der Headerdatei <time.h>
725
20.1.2 Datums- und Zeitfunktionen in <time.h>
725
20.2 Laufzeitmessung (Profiling)
735
20.3 Besonderheiten beim Raspberry Pi
737
21 Weitere Headerdateien und ihre Funktionen (ANSI C)
739
21.1 Testmöglichkeiten und Fehlersuche – <assert.h>
739
21.2 Zeichenklassifizierung und Umwandlung – <ctype.h>
741
21.3 Mathematische Funktionen – <math.h>, <tgmath.h> und <complex.h>
746
21.3.1 Funktionen für reelle und komplexe Gleitpunkttypen
747
21.3.2 Funktionen nur für reelle Gleitpunkttypen
749
21.3.3 Funktionen nur für komplexe Gleitpunkttypen
751
21.3.4 Typengenerische Makros – <tgmath.h>
752
21.3.5 Gleitpunktwerte klassifizieren
754
21.3.6 Makro zum Vergleichen von reellen Zahlen
755
21.3.7 Zugriff auf die Gleitpunktumgebung – <fenv.h>
756
21.4 Einige nützliche Funktionen in <stdlib.h>
759
21.4.1 Programmbeendigung – »exit()«, »_exit()«, »atexit()« und »abort()«
759
21.4.2 Strings in numerische Werte konvertieren
763
21.4.3 Bessere Alternative – Strings in numerische Werte konvertieren
765
21.4.4 Zufallszahlen
770
21.4.5 Absolutwerte, der Quotient und der Rest von Divisionen
773
21.4.6 Suchen und Sortieren – »qsort()« und »bsearch()«
774
21.4.7 »system()«
777
21.5 Länderspezifische Eigenheiten – <locale.h>
779
21.6 Nichtlokale Sprünge – <setjmp.h>
783
21.7 Einige nützliche Funktionen in <signal.h>
787
21.8 Die »mem…«-Funktionen zur Speichermanipulation – <string.h>
792
21.8.1 »memchr()« – Suche nach einzelnen Zeichen
793
21.8.2 »memcmp()« – bestimmte Anzahl von Bytes vergleichen
793
21.8.3 »memcpy()« – bestimmte Anzahl von Bytes kopieren
794
21.8.4 »memmove()« – bestimmte Anzahl von Bytes kopieren
795
21.8.5 »memset()« – Speicherbereich mit bestimmten Zeichen auffüllen
796
22 Dynamische Datenstrukturen
797
22.1 Lineare Listen (einfach verkettete Listen)
797
22.1.1 Erstes Element der Liste löschen
805
22.1.2 Ein beliebiges Element in der Liste löschen
807
22.1.3 Elemente der Liste ausgeben
810
22.1.4 Eine vollständige Liste auf einmal löschen
815
22.1.5 Element in die Liste einfügen
818
22.2 Doppelt verkettete Listen
831
22.3 Stacks nach dem LIFO-(Last-in-first-out-)Prinzip
849
22.4 Queues nach dem FIFO-Prinzip
869
22.5 Dynamisches Array mit flexiblen Elementen
878
23 Algorithmen
881
23.1 Was sind Algorithmen?
881
23.2 Beispiele für Algorithmen
883
23.2.1 Sortieralgorithmen
883
23.2.2 Suchalgorithmen und Bäume
911
23.2.3 Stringmatching
940
23.2.4 Pattern Matching durch reguläre Ausdrücke
952
23.2.5 Backtracking
959
23.2.6 Der Weg durch den Irrgarten
959
23.2.7 Kryptografische Hashing-Algorithmen
974
23.2.8 Wozu benötigt man Hashing in der Kryptografie?
974
23.2.9 Wichtige kryptografische Hashing-Verfahren
974
24 MySQL und C
989
24.1 Aufbau eines Datenbanksystems
989
24.1.1 Warum wurden Datenbanksysteme (DBS) entwickelt?
990
24.1.2 Das Datenbank-Management-System (DBMS)
991
24.1.3 Relationale Datenbanken
993
24.1.4 Mit C eigene Clients für SQL entwickeln mithilfe der ODBC-API
994
24.2 MySQL installieren
995
24.2.1 Linux
995
24.2.2 Windows
996
24.2.3 Den Client »mysql« starten
997
24.3 Crashkurs SQL
999
24.3.1 Was ist SQL?
999
24.3.2 Die Datentypen von (My)SQL
1000
24.3.3 Eine Datenbank erzeugen
1002
24.3.4 Eine Datenbank löschen
1003
24.3.5 Datenbank wechseln
1004
24.3.6 Eine Tabelle erstellen
1004
24.3.7 Die Tabelle anzeigen
1005
24.3.8 Tabellendefinition überprüfen
1005
24.3.9 Tabellen löschen
1006
24.3.10 Ein Backup erstellen
1006
24.3.11 Die Struktur einer Tabelle ändern
1006
24.3.12 Datensätze einfügen
1007
24.3.13 Datensätze auswählen
1007
24.3.14 Ein fortgeschrittenes Szenario
1009
24.3.15 Datensätze löschen
1010
24.3.16 Datensatz ändern
1011
24.3.17 Zugriffsrechte in MySQL
1011
24.3.18 Übersicht über einige SQL-Kommandos
1012
24.4 Die MySQL-C-API
1014
24.4.1 Grundlagen zur Programmierung eines MySQL-Clients
1014
24.4.2 Client-Programm mit dem GCC unter Linux und dem Cygwin-GCC-Compiler unter Windows
1015
24.4.3 MySQL Client-Programme mit dem VC++ Compiler und dem Borland Freeware Compiler
1016
24.4.4 Troubleshooting
1018
24.4.5 Das erste Client-Programm – Verbindung mit dem MySQL-Server herstellen
1018
24.4.6 MySQL-Kommandozeilen-Optionen
1023
24.4.7 Anfrage an den Server
1026
24.5 MySQL und C mit CGI
1045
24.5.1 HTML-Eingabeformular
1045
24.5.2 Die CGI-Anwendung »add_db.cgi«
1047
24.5.3 Die CGI-Anwendung »search_db.cgi«
1054
24.6 Funktionsübersicht
1063
24.7 Datentypenübersicht der C-API
1066
24.8 Weiterführende Literatur zu Datenbanken
1067
25 Netzwerkprogrammierung und Cross-Plattform-Entwicklung
1069
25.1 Begriffe zur Netzwerktechnik
1070
25.1.1 Ethernet-Frames
1070
25.1.2 IP-Adressen
1071
25.1.3 Portnummern
1073
25.1.4 Host- und Domainnamen
1074
25.1.5 Nameserver
1074
25.1.6 Das IP-Protokoll
1075
25.1.7 TCP und UDP
1075
25.2 Was sind Sockets und wie legt man sie in C an?
1076
25.3 Headerdateien für die Netzwerkprogrammierung
1077
25.3.1 Linux/UNIX
1077
25.3.2 Windows
1078
25.4 Das Client-Server-Prinzip
1080
25.5 Erstellen einer Client-Anwendung
1082
25.5.1 »socket()« – Erzeugen eines Kommunikationsendpunktes
1082
25.5.2 »connect()« – ein Client stellt eine Verbindung zum Server her
1084
25.5.3 Senden und Empfangen von Daten
1089
25.5.4 »close()« und »closesocket()«
1092
25.6 Erstellen einer Server-Anwendung
1092
25.6.1 »bind()« – Festlegen einer Adresse aus dem Namensraum
1092
25.6.2 »listen()« – Warteschlange für eingehende Verbindungen einrichten
1094
25.6.3 »accept()« und die Server-Hauptschleife
1095
25.7 Ein einfacher TCP-Echo-Server
1098
25.7.1 Der Client
1098
25.7.2 Der Server
1101
25.8 Cross-Plattform-Development
1105
25.8.1 Abstraction Layer
1105
25.8.2 Headerdatei für Linux/UNIX
1106
25.8.3 Linux/UNIX-Quellcodedatei
1107
25.8.4 Headerdatei für MS-Windows
1111
25.8.5 Windows-Quellcodedatei
1111
25.8.6 All together – die »main()«-Funktionen
1115
25.8.7 Ein UDP-Beispiel
1118
25.8.8 Mehrere Clients gleichzeitig behandeln
1121
25.9 Weitere Anmerkungen zur Netzwerkprogrammierung und Literaturempfehlungen
1128
25.9.1 Das Datenformat
1128
25.9.2 Der Puffer
1129
25.9.3 Portabilität
1130
25.9.4 Von IPv4 nach IPv6
1130
25.9.5 RFC-Dokumente (Request for Comments)
1132
25.9.6 Sicherheit
1132
25.9.7 Literaturempfehlungen
1133
26 Paralleles Rechnen
1135
26.1 Was ist Multitasking und wie wird es realisiert?
1135
26.2 Braucht man spezielle Prozessoren für Multitasking?
1136
26.2.1 Single-Prozessorsysteme
1137
26.2.2 Hyperthreading
1138
26.3 Braucht man spezielle Multitasking-Betriebssysteme?
1139
26.4 Programmiertechniken der Parallelisierung
1139
26.4.1 Automatische Parallelisierung
1139
26.4.2 Halbautomatische Parallelisierung
1139
26.4.3 Echte Parallelisierung
1140
26.5 Vom Prozess zum Thread
1140
26.6 Mit POSIX-Threads programmieren
1144
26.6.1 Ein serielles Beispiel
1144
26.6.2 Das Grundgerüst für ein Programm mit mehreren Threads
1146
26.6.3 Zusammenfassung
1152
27 Sicheres Programmieren
1153
27.1 Buffer Overflow (Speicherüberlauf)
1154
27.1.1 Was verursacht Buffer Overflows?
1154
27.1.2 Warum sind Buffer Overflows kritisch für die Sicherheit?
1155
27.1.3 Wie man Buffer Overflows vermeidet
1164
27.1.4 Gegenmaßnahmen zum Buffer Overflow, wenn das Programm fertig ist
1168
27.2 Stack Overflow (Stapelüberlauf)
1172
27.2.1 Was verursacht Stack Overflows?
1173
27.2.2 Warum ist ein Stapelüberlauf kritisch für die Sicherheit?
1173
27.2.3 Wie man Stack Overflows verhindert
1173
27.3 Memory Leaks (Speicherlecks)
1174
27.3.1 Bibliotheken und Tools zu Memory Leaks
1178
27.3.2 Tipps zu Sicherheitsproblemen
1180
27.4 Weiterführende Literatur zu sicherem Programmieren
1180
28 Wie geht’s jetzt weiter?
1181
28.1 GUI-Programmierung – grafische Oberflächen
1182
28.1.1 Low-Level-Grafikprogrammierung
1182
28.1.2 High-Level-Grafikprogrammierung
1183
28.1.3 RAD-Tools
1184
28.1.4 Multimedia-Grafikprogrammierung
1184
28.2 Grafikprogrammierung unter Windows
1185
28.2.1 Das Gerätekontext-Handle (HDC)
1189
28.2.2 Über das HDC in ein Fenster zeichnen (Visual Studio 2013 und höher)
1190
28.2.3 Über ein HDC in die Konsole zeichnen (Borland C++ 5.5)
1193
28.2.4 Die Methode BitBlt
1195
28.2.5 Grafiken im Fenster schnell auffrischen
1196
28.3 Grafikprogrammierung unter Linux (Beispiel Raspberry Pi)
1197
28.3.1 Die Framebuffer-Gerätedatei
1198
28.3.2 In den Framebuffer zeichnen
1198
28.3.3 Den Bildschirminhalt schnell auffrischen
1199
28.3.4 Ein paar Grafikprimitiven
1202
28.3.5 Weiterführende Literatur zum Thema Grafikprogrammierung
1205
Anhang
1207
A Operatoren
1207
A.1 Rangfolge der Operatoren
1207
A.2 ASCII-Code-Tabelle
1209
A.3 Reservierte Schlüsselwörter in C
1210
A.4 Standard-Headerdateien der ANSI-C-Bibliothek
1210
Index
1213