0% fanden dieses Dokument nützlich (0 Abstimmungen)
66 Ansichten486 Seiten

CPP 123 Uo 00 Es 0119

Das Dokument ist eine Publikation des Markt+Technik Verlags über die Programmiersprachen C und C++. Es enthält umfassende Informationen zu Grundlagen, Sprachkonzepten, Syntax und typischen Komponenten von C/C++-Programmen. Zudem wird auf den ANSI-Standard, objektorientiertes Programmieren und die Verwendung von Standardbibliotheken eingegangen.

Hochgeladen von

jasoncxq666
Copyright
© © All Rights Reserved
Wir nehmen die Rechte an Inhalten ernst. Wenn Sie vermuten, dass dies Ihr Inhalt ist, beanspruchen Sie ihn hier.
Verfügbare Formate
Als PDF, TXT herunterladen oder online auf Scribd lesen
0% fanden dieses Dokument nützlich (0 Abstimmungen)
66 Ansichten486 Seiten

CPP 123 Uo 00 Es 0119

Das Dokument ist eine Publikation des Markt+Technik Verlags über die Programmiersprachen C und C++. Es enthält umfassende Informationen zu Grundlagen, Sprachkonzepten, Syntax und typischen Komponenten von C/C++-Programmen. Zudem wird auf den ANSI-Standard, objektorientiertes Programmieren und die Verwendung von Standardbibliotheken eingegangen.

Hochgeladen von

jasoncxq666
Copyright
© © All Rights Reserved
Wir nehmen die Rechte an Inhalten ernst. Wenn Sie vermuten, dass dies Ihr Inhalt ist, beanspruchen Sie ihn hier.
Verfügbare Formate
Als PDF, TXT herunterladen oder online auf Scribd lesen

Dirk Louis

C/C++
new reference

Markt+Technik Verlag
Die Deutsche Bibliothek – CIP-Einheitsaufnahme

Ein Titeldatensatz für diese Publikation ist


bei Der Deutschen Bibliothek erhältlich.

Die Informationen in diesem Produkt werden ohne Rücksicht auf einen


eventuellen Patentschutz veröffentlicht.
Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt.
Bei der Zusammenstellung von Texten und Abbildungen wurde mit größter
Sorgfalt vorgegangen.
Trotzdem können Fehler nicht vollständig ausgeschlossen werden.
Verlag, Herausgeber und Autoren können für fehlerhafte Angaben
und deren Folgen weder eine juristische Verantwortung noch
irgendeine Haftung übernehmen.
Für Verbesserungsvorschläge und Hinweise auf Fehler sind Verlag und
Herausgeber dankbar.

Alle Rechte vorbehalten, auch die der fotomechanischen


Wiedergabe und der Speicherung in elektronischen Medien.
Die gewerbliche Nutzung der in diesem Produkt gezeigten
Modelle und Arbeiten ist nicht zulässig.

Fast alle Hardware- und Software-Bezeichnungen, die in diesem Buch


erwähnt werden, sind gleichzeitig auch eingetragene Warenzeichen
oder sollten als solche betrachtet werden.

Umwelthinweis:
Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt.
Die Einschrumpffolie – zum Schutz vor Verschmutzung – ist aus
umweltverträglichem und recyclingfähigem PE-Material.

10 9 8 7 6 5 4 3 2 1

04 03 02 01

ISBN 3-8272-6121-X

© 2001 by Markt+Technik Verlag,


ein Imprint der Pearson Education Deutschland GmbH.
Martin-Kollar-Straße 10–12, D–81829 München/Germany
Alle Rechte vorbehalten
Einbandgestaltung: Helfer Grafik Design, München
Lektorat: Erik Franz, efranz@[Link]
Herstellung: Anja Zygalakis, azygalakis@[Link]
Satz: reemers publishing services gmbh, Krefeld ([Link])
Druck und Verarbeitung: Media-Print, Paderborn
Printed in Germany
Inhaltsverzeichnis

Inhaltsverzeichnis
Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Die Programmiersprachen C und C++. . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Leistungsmerkmale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Der ANSI-Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Schreibkonventionen in C/C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Aufbau eines C/C++-Programms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Typische Komponenten von C/C++-Programmen . . . . . . . . . . . . . . . . . . 20
Größere Programme und Modularisierung . . . . . . . . . . . . . . . . . . . . . . . . 26
Objektorientiertes Programmieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Verwendung der Standardbibliotheken . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Ein- und Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Programmfluß . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Programmerstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

Sprachkonzepte und Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41


Elemente der Sprache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Zeichensatz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Trigraphsequenzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Schlüsselwörter und Symbole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Eigene Bezeichner: Definition und Deklaration . . . . . . . . . . . . . . . . . . . . 46
Variablen und Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Variablen und Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Die elementaren Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Speicherbelegung der Integer-Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Speicherbelegung der Gleitkommatypen . . . . . . . . . . . . . . . . . . . . . . . . . 52
Vorzeichen integraler Datenypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

5
Inhaltsverzeichnis

Variablendeklaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Gültigkeitsbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Namensbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Sichtbarkeit und Verdeckung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Lebensdauer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Zusammengesetzte Datentypen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Zusammengesetzte Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Aufzählungstypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Mehrdimensionale Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
Zeichenketten (Strings) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Strukturen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Bitfelder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Zeiger und Referenzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Zeiger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Spezielle Zeiger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Referenzen (nur C++) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Typdefinitonen und Typumwandlungen . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Typdefinitionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Standardkonvertierungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Typumwandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Literale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
#define – symbolische Konstanten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
const – konstante Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Vorzeichen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Arithmetische Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
In- und Dekrementoperator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Zuweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Vergleichende Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Logische Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Datenzugriff . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
Bitweise Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Streamoperatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
Die Operatoren new und delete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Typumwandlung und -identifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
Sonstige Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Synonyme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Priorität und Assoziativität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Überladung von Operatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
Programmsteuerung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Programmsteuerung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

6
Inhaltsverzeichnis

Die if-Bedingung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132


Die if-else-Verzweigung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
if-else-Ketten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
switch-Verzweigung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
Die for-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Die while-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Die do-while-Schleife . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Abbruchbefehle für Schleifen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Funktionsdeklaration und -definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Die Funktion main() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
Datenaustausch zwischen Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Der Rückgabewert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
Parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
Funktionsargumente und Vorgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Funktionen und der Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Funktionen mit beliebig vielen Argumenten . . . . . . . . . . . . . . . . . . . . . . . 157
Inline-Funktionen (nur C++) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Spezifizierer für Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Überladung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
Überladung von Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Überladung von Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
Überladen, Überschreiben, Verdecken . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Klassen und OOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
Kapselung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Datenelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
Statische Datenelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Konstante Datenelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
Klasseninstanzen als Datenelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
Lokale und verschachtelte Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Statische Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Konstante Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Zugriffsspezifizierer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Zugriff innerhalb der Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
Zugriff von außerhalb der Klasse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Zugriff auf Basisklassenelemente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Der Konstruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
Der Kopierkonstruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Der Destruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Standardmethoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
Der this-Zeiger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187

7
Inhaltsverzeichnis

Instanzbildung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
Vererbung und Polymorphie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Vererbung versus Einbettung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
Zugriffsbeschränkung bei der Vererbung . . . . . . . . . . . . . . . . . . . . . . . . . 192
Zugriffsrechte für einzelne Elemente auflockern . . . . . . . . . . . . . . . . . . . . 194
Vererbung und Konstruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
Nicht vererbbare Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Polymorphie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Überschreibung und virtuelle Methoden . . . . . . . . . . . . . . . . . . . . . . . . . 199
Vererbung und Destruktor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Abstrakte Methoden und Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Basisklassenzeiger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
RTTI – Laufzeittypidentifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
Mehrfachvererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
Virtuelle Basisklassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
Funktionentemplates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
Klassentemplates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
Methoden in Klassentemplates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
Instanziierung und Spezialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
Implizite Instanziierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
Explizite Instanziierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Explizite Spezialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
Der Präprozessor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
Quellcode einfügen und ersetzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
Makros definieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
Argumente in Makros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Direktiven zur bedingten Kompilierung . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Zeichenkettenbildung und Grundsymbolverbindung . . . . . . . . . . . . . . . . 224
Sonstige Direktiven und Symbole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
Exception-Behandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Exception-Behandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
Exceptions auslösen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
Exceptions abfangen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
Handler-Bereich festlegen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
Verwandte Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
Zeichenketten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
C-Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
Die Klasse string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
Wide characters und Multibyte-Zeichen . . . . . . . . . . . . . . . . . . . . . . . . . 238
Ein- und Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Formatierte und unformatierte E/A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Streams in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
Streams in C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
Pufferung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246

8
Inhaltsverzeichnis

Die C-Standardbibliothek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247


Die Header-Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
assert.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
ctype.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
errno.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
float.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
ios646.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
limits.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
locale.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
math.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
setjmp.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
signal.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
stdarg.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
stddef.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
stdio.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
stdlib.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
string.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
time.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
wchar.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
wctype.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
Die Funktionen der C-Standardbibliothek . . . . . . . . . . . . . . . . . . . . . . . . 264

Die C++-Standardbibliothek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329


Übersicht über die Standardbibliothek . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
Die Header-Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
bitset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
complex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
deque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
fstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
functional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 336
iomanip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
ios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
iosfwd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
iostream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
istream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
iterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
locale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
numeric . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
ostream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349

9
Inhaltsverzeichnis

queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
sstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
stdexcept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
streambuf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
typeinfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
valarray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354
vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
Die Container-Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
Allgemeine Eigenschaften . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
bitset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
deque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
map und multimap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
priority_queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
set und multiset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
Die Iteratoren-Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
Allgemeines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
reverse_iterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
Insert-Iteratoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
Stream-Iteratoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
Unterstützung eigener Implementierungen . . . . . . . . . . . . . . . . . . . . . . . . 390
Die Algorithmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
Die Stream-Klassen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
ios_base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
basic_ios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
basic_streambuf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
basic_istream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
basic_ostream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
basic_iostream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
basic_stringbuf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
basic_istringstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413
basic_ostringstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
basic_stringstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
basic_filebuf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
basic_ifstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
basic_ofstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
basic_fstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419
Die String-Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420

10
Inhaltsverzeichnis

Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
char_traits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
basic_string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421
Die Klassen zur lokalen Einstellung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
Übersicht . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
locale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
Die Hilfsklassen für die einzelnen Kategorien . . . . . . . . . . . . . . . . . . . . . . 428
Die numerischen Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
complex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
valarray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444
Teilmengen von valarray-Objekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
numeric_limits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
Klassen und Funktionen zur Exception-Behandlung . . . . . . . . . . . . . . . . . 453
exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
Abgeleitete Exception-Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
Funktionen zur Exception-Behandlung . . . . . . . . . . . . . . . . . . . . . . . . . . 456
Laufzeittypidentifizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
type_info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
Die Struktur pair . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
Funktionsobjekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
Speicherallokation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
allocator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
auto_ptr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
Funktionen und Iteratoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467

11
C/C++
new reference
Übersicht
Grundlagen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Sprachkonzepte und Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Die C-Standardbibliothek. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
Die C++-Standardbibliothek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329

13
Grundlagen

Grundlagen

Die Programmiersprachen C und C++


Im Gegensatz zu anderen Hochsprachen wie Pascal oder Basic, die ursprünglich als
reine Lehrsprachen konzipiert wurden, verdankt C seine Entstehung dem Umstand,
daß man bei Bell Laboratories eine höhere Programmiersprache für die Implemen-
tierung eines neu entwickelten Betriebssystems suchte. Bis dato programmierte man
das gesamte Betriebssystem, das später als UNIX bekannt wurde, nämlich in
Assembler. Um sich die Arbeit zu erleichtern, bastelte man an einer eigenen
Programmiersprache, die möglichst effizient, gut zu portieren und leicht zu compi-
lieren sein sollte.
Brian W. Kernighan und Dennis M. Ritchie waren es, die diese Bemühungen zum
Erfolg führten und gleichzeitig eine der leistungsfähigsten Programmiersprachen
überhaupt schufen: die Programmiersprache C. In der Folgezeit fand C schnell
weite Verbreitung und wurde aufgrund seiner Qualitäten und trotz der Schwierig-
keiten, denen sich gerade Anfänger bei der Erlernung dieser Sprache gegenüber
sehen, immer beliebter.
Mit der Zeit wandelten sich die Anforderungen an eine professionelle Program-
miersprache. Neben der Erzeugung schneller und kompakter Codes trat die Wart-
barkeit und Wiederverwertung bestehender Codes immer weiter in den Vorder-
grund, und damit auch das Interesse an objektorientierten Konzepten.
Mitte der Achtziger begann Bjarne Stroustrup C um objektorientierte Konzepte zu
erweitern. Die Betonung liegt dabei auf dem Wort »Erweiterung«, denn die Kom-
patibilität zu C war bei der Entwicklung der neuen Programmiersprache ein vor-
dringliches Designmerkmal. Eine der ersten Stationen auf dem Weg zur neuen
Programmiersprache wurde daher noch als »C mit Klassen« bezeichnet. 1985 kam
dann eine Version heraus, die bereits zurecht als objektorientierte Programmier-
sprache gelten kann, und die unter dem Namen C++ bekannt wurde. Mittlerweile
ist C++ voll ausgereift und ebenso erfolgreich wie C.
Ein Grund hierfür ist sicherlich die (nahezu) vollständige Abwärtskompatibilität zu
C, die dem C-Programmierer den Einstieg in die objektorientierte Programmierung
wesentlich erleichtert und die Verwertbarkeit bereits existierenden C-Codes garan-
tiert.

14
Leistungsmerkmale

Im Gegensatz zu rein objektorientierten Sprachen wie Modula oder Smalltalk


besteht damit allerdings auch die Gefahr, C++ lediglich als weniger strikte C-Ver-
sion einzusetzen. Programmieren in C++ ist daher nicht automatisch mit objekt-
orientierter Programmierung gleichzusetzen.

Leistungsmerkmale
C wurde ursprünglich als High-Level-Sprache zur Systemprogrammierung, nament-
lich der Entwicklung des Betriebssystems UNIX, konzipiert. Insofern war C nur ein
untergeordnetes Hilfsmittel, und C-Programme sollten einfach zu kompilieren und
schnell sein. Das Ergebnis war eine Sprache, die sich durch
● ihren geringen Umfang an Sprachelementen,
● die schnelle Laufzeit ihrer Programme,
● die Unterstützung modularer Programmierung und
● ihrer guten Portabilität bei gleichzeitiger Systemnähe
auszeichnete.
Heutzutage sieht die Situation so aus, daß Rechenzeit immer billiger und der Pro-
grammieraufwand immer kostspieliger wird. Ziel der objektorientierten Program-
mierung mit C++ ist es daher, Quelltext zu schaffen, der sich durch
● einfache und sichere Verwendung,
● hohe Wiederverwertbarkeit,
● einfache Wartbarkeit,
● gute Verständlichkeit und Lesbarkeit
auszeichnet.

Der ANSI-Standard
Der Erfolg einer Programmiersprache hängt nicht nur von der Sprache selbst,
sondern auch von der Verfügbarkeit passender Compiler (oder Interpreter) und
unterstützender Bibliotheken ab. Letztere waren für die Verbreitung von C sogar
von besonderer Bedeutung, da es in C für viele zentralen Aufgaben (Ein- und Aus-
gabe, Stringbearbeitung, dynamische Speicherverwaltung) keine in der Sprache ver-
ankerte Elemente gibt.
Die Abhängigkeit von Standardbibliotheken bedeutet aber auch zusätzliche Abhän-
gigkeit von den Compiler-Entwicklern. Um diesem Einfluß entgegenzuwirken und zu
verhindern, daß jeder C-Compiler-Entwickler seinen eigenen C-Dialekt definiert, trat
im Jahre 1983 im American National Standard Institute (ANSI) ein Komitee aus

15
Grundlagen

Compiler-Herstellern, Software-Entwicklern und Hardware-Produzenten zusam-


men, das einen Standard für die Programmiersprache C erarbeiten sollte. Der 1989
ratifizierte Standard (Referenznummer ISO/IEC 9899:1990) definiert sowohl Syntax
und Semantik der Sprache wie auch die Zusammensetzung der Standardbibliothek.
Programmierer, die sich an die vom Standard vorgegebenen Regeln halten und
keine plattformspezifischen Funktionen verwenden (beispielsweise Programmierung
mit DOS-Interrupts), können dank des ANSI-Standards sicher sein, daß sie ihr Pro-
gramm von jedem ANSI-kompatiblen Compiler erstellen lassen können. Dies
bedeutet aber auch, daß man ein Programm auf jedes beliebige System (Computer/
Betriebssystem) portieren kann, sofern es nur einen passenden ANSI-kompatiblen
Compiler für dieses System gibt.
1995 wurde die C-Standardbibliothek um eine Sammlung von Funktionen zur Pro-
grammierung mit sogenannten Wide Characters – Zeichen, die durch 16- und 32-
Bit-Zeichencodes codiert werden – ergänzt. Bei den meisten dieser Funktionen, die
in den neuen Headern wchar.h und wctype.h deklariert sind, handelt es sich um
Adaptionen bestehender C-Funktionen an den Zeichentyp wchar_t. Die Erweiter-
ungen sind im Amendment ISO/IEC 9899:1990/Amd.1:1995(E) zusammengefaßt.
Auch für C++ gibt es mittlerweile einen ANSI-Standard. Die wichtigsten Neuerun-
gen gegenüber dem bis dato geltenden Quasi-Standard von Bjarne Stroustrup dürf-
ten in der Einführung von Namensbereichen als frei definierbare globale Gültig-
keitsbereiche und der Standardisierung der C++-Laufzeitbibliothek zu sehen sein.
Die Ausführungen und Beschreibungen in diesem Buch richten sich nach dem
neuen C++-Standard. Im Praxisteil dieses Buches finden Sie viele Abschnitte, die
zeigen, wie man die Klassen der C++-Laufzeitbibliothek bei der täglichen Program-
mierarbeit nutzen kann.
Obwohl die Abwärtskompatibilität zu C bei der Entwicklung von C++ höchste
Priorität hatte, wurden einige wenige der von C übernommenen Konzepte und Ele-
mente in ihrer Semantik geändert (siehe Anhang). Sollte sich ein C-Programm nach
der Kompilation mit einem C++-Compiler anders als zuvor verhalten, sollte man
prüfen, ob das Programm von diesen Änderungen betroffen ist.

Bezugsquellen
C- und C++-Standard können Sie online beim ANSI-Institut oder IHS (Information
Handling Service) anfordern:
[Link]
[Link]
Kopien der Standards können auch aus der Schweiz
ISO/IEC Copyright Office
Case Postale 56
CH-1211 Genève 20
Schweiz

16
Schreibkonventionen in C/C++

oder aus München bezogen werden:


IHS Information Handling Services
Tel. 089 / 89526999
Den abschließenden C++-Draft kann man sich derzeit noch aus dem Internet her-
unterladen:
[Link]

Schreibkonventionen in C/C++
Bei der Festlegung der Namen von Bezeichnern, das sind Variablen-, Funktions-,
Klassen-, Typen- und Makronamen, dürfen folgende Zeichen benutzt werden:
● alle Buchstaben des englischen Alphabets (a bis z, A bis Z)
● die Ziffern 0 bis 9
● der Unterstrich »_«
● Der Name eines Bezeichners muß mit einem Buchstaben oder dem Unterstrich
beginnen. Die Verwendung einer Ziffer als ersten Buchstaben eines Bezeich-
ners ist nicht erlaubt.
● Die deutschen Umlaute und andere Sonderzeichen dürfen also nur in Kom-
mentaren und in Zeichenketten vorkommen.
● Die maximale Länge der Bezeichner ist nicht vorgeschrieben, jedoch müssen
nach ANSI C mindestens die ersten 31 Zeichen zur Unterscheidung herange-
zogen werden.

Warnung
Die Sprache C unterscheidet zwischen Groß- und Kleinschreibung. Die Bezeichner
var1 und Var1 können also für zwei verschiedene Variablen benutzt werden.

Aufbau eines C/C++-Programms


#include <stdio.h>
int main()
{
/* Anweisungen */
return 0;
}

17
Grundlagen

Beschreibung
C/C++-Programme bestehen aus einer Ansammlung von Deklarationen und Definitionen von
Datentypen, Variablen, Funktionen und Klassen (sowie einigen speziellen Direktiven an den
Präprozessor). Anweisungen, die festlegen, was ein Programm macht, findet man nur innerhalb
von Funktionsdefinitionen (in C++ auch in den Methoden (Elementfunktionen) der Klassen).
Jedes C/C++-Programm muß eine main()-Funktion definieren, mit deren Ausführung das
Programm beginnt.

Anwendung
Im einfachsten Fall besteht ein C/C++-Programm
● aus einer oder mehreren include-Direktiven, die den Zugriff auf bestimmte
Funktionen und Klassen der C/C++-Standardbibliotheken ermöglichen, sowie
● der obligatorischen Funktion main(), in der alle Anweisungen zur Ausführung
des Programms stehen,
● aus Variablen, die deklariert werden, um Werte zu repräsentieren und zwi-
schenzuspeichern,
● aus Anweisungen, in denen die Werte in den Variablen bearbeitet werden.

Beispiel
Um ein einfaches Programm aufzusetzen, das zwei Zahlen multipliziert und das
Produkt der beiden Zahlen ausgibt, könnte man folgendermaßen vorgehen:
Um zwei ganzzahlige Werte im Programm verwalten zu können, deklariert man
zwei Variablen des Datentyps int (Datentyp für ganzzahlige Werte). Für das Ergeb-
nis kann man eine dritte Variable definieren.
int main()
{
int zahl1, zahl2;
int ergebnis;
Mit Hilfe des Zuweisungsoperators kann man den Variablen Werte zuweisen:
int main()
{
...
zahl1 = 120; /* Werte zuweisen */
zahl2 = 4;
Zur Multiplikation von int-Werten verwendet man den *-Operator. Das Ergebnis
der Berechnung weist man direkt der dritten Variablen zu.
ergebnis = zahl1 * zahl2;

18
Aufbau eines C/C++-Programms

Um Werte auszugeben, kann man sich einer speziellen Funktion namens printf()
bedienen, die Teil der C-Laufzeitbibliothek ist.
printf("Das Produkt der Zahlen ist : %d\n", ergebnis);
Bevor man eine Funktion aufruft, muß die Funktion allerdings dem Compiler per
Deklaration bekanntgemacht worden sein. Die Deklarationen für die Funktionen
der Laufzeitbibliothek sind in einer Reihe von Header-Dateien zusammengefaßt.
Nachdem man sich erkundigt hat, in welcher Header-Datei die gewünschte Funk-
tion deklariert ist, bindet man die Header-Datei mittels einer #include-Anweisung
am Anfang des Programms ein.
#include <stdio.h>

Warnung
Leser, die mit C/C++ für Windows programmieren wollen, seien darauf hingewie-
sen, daß Windows-Programme statt der main()-Funktion die Funktion WinMain()
verwenden. Je nach verwendetem Compiler und Klassenbibliothek kann WinMain()
selbst wieder durch eine andere Funktion (beispielsweise OwlMain() für Borland C++
mit OWL) oder eine Klasseninstanz (beispielsweise ein globales Objekt der MFC-
Klasse CWinApp in Visual C++) ersetzt sein.
Konsolenprogramme, die unter Windows ausgeführt werden (sprich im Fenster der
MS-DOS-Eingabeaufforderung ablaufen und über keine eigene Windows-Oberflä-
che verfügen), verwenden aber wie reine DOS- oder UNIX-Programme die main()-
Funktion.

Beispiel
Das folgende Programm kann nach der Kompilation von der Konsole (unter Win-
dows die MS-DOS-Eingabeaufforderung) Ihres Betriebssystems aus aufgerufen und
ausgeführt werden.
#include <stdio.h>

int main()
{
int zahl1, zahl2; /* Faktoren */
int ergebnis; /* Produkt */

zahl1 = 120; /* Werte zuweisen */


zahl2 = 4;
ergebnis = zahl1 * zahl2; /* Wert berechnen */

printf("Das Produkt der Zahlen ist : %d\n", ergebnis);

return 0;
}

19
Grundlagen

Verweise
Siehe nachfolgende Abschnitte für weitere einführende Informationen zum Aufbau
von C/C++-Programmen.
Siehe Kapitel zur Sprache für detaillierte Informationen zu Variablen, Datentypen,
Operatoren, Funktionen.

Typische Komponenten von C/C++-Programmen


/* Das erste C-Programm */ Kommentar
#include <stdio.h> Präprozessor-Direktive
Funktion
int main()
{
Anweisungs printf("Hello World\n");
-block Anweisungen
return 0;
}

Typische Komponenten eines C/C++-Programms

Beschreibung
Die Funktionalität eines Programmes wird bestimmt durch die Daten, die es verarbeitet, und die
Operationen, die es auf den Daten ausführt. Insofern könnte man meinen, ein Programm
bestünde nur aus Variablendefinitionen und Anweisungen. Dem ist aber nicht so. Der Compiler
unterscheidet noch ganz andere Elemente.

20
Typische Komponenten von C/C++-Programmen

Aus Sicht des Compilers besteht ein Programm aus:


– Definitionen
– Deklarationen
– Anweisungen
– Präprozessor-Direktiven
– Kommentaren

Definitionen und Deklarationen


Bei Ausführung des Programms müssen der Code und die Daten des Programms in
den Arbeitsspeicher des Computers geladen werden. Welcher Code und welche
Daten zu einem Programm gehören, legen Sie beim Aufsetzen des Quelltextes selbst
fest.
Der Code des Programms besteht aus den in Maschinencode übersetzten Anwei-
sungen aus dem Quelltext. In C/C++ dürfen Anweisungen nur in Funktionsdefini-
tionen stehen. Indem Sie eine Funktion definieren, beispielsweise die main()-Funk-
tion des Programms, teilen Sie dem Compiler mit, daß er für die Funktion Speicher
reservieren und dafür Sorge tragen soll, daß der Code der Funktion bei Aufruf des
Programms an die entsprechende Stelle im Speicher geladen wird.
Für die Verwaltung der Daten definieren Sie Variablen. Hinter den Variablen
stehen Speicherbereiche im RAM, die der Compiler für Sie reserviert. In den Varia-
blen können Sie die Daten Ihres Programms speichern.
Durch eine Definition führt man neue Elemente (Funktionen, Variablen, Daten-
typen) in ein Programm ein. Gleichzeitig wird das Element im Zuge der Definition
mit einem Bezeichner verbunden (Variablenname, Funktionsname, etc.), der im
Programmquelltext verwendet wird, um auf das Element zuzugreifen.
Da mit der Definition von Funktionen und Variablen die Bereitstellung von Spei-
cherbereichen einhergeht, müssen diese Elemente eindeutig sein, d. h., sie dürfen
nur einmal im ganzen Programm definiert sein (sonst gäbe es Bezeichner, die mit
mehreren Speicherbereichen assoziert wären). Andererseits fordert der Compiler,
daß alle Elemente, die man verwendet, ihm vorab bekanntgemacht werden müssen.
Bevor man eine Variable verwendet, muß man dem Compiler mitteilen, welchen
Datentyp die Variable hat, bevor man eine Funktion aufrufen kann, muß man dem
Compiler mitteilen, welche Parameter die Funktion übernimmt und was für einen
Rückgabetyp sie zurückliefert. Die Bekanntmachung der Elemente bezeichnet man
als Deklaration. Grundsätzlich ist jede Definition auch eine Deklaration. Es gibt
aber auch die Möglichkeit, Elemente zu deklarieren, ohne daß man die Elemente
neu deklariert. Für Variablen stellt man dabei der »Definition« das Schlüsselwort
extern voran, für Funktionen gibt man nur den Funktionskopf (Rückgabetyp,
Name, Parameterliste) ohne Anweisungsteil an.

21
Grundlagen

Verweise
Siehe Elemente der Sprache.

Variablen und Konstanten


Feste Werte, die sich im Laufe des Programms nicht ändern oder nur einmal benö-
tigt werden, kann man direkt in Form von Literalen in den Quelltext schreiben.
Für veränderliche Werte definiert man Variablen. Der Compiler weist der Varia-
blen einen Speicherbereich zu, in den man im Laufe des Programms verschiedene
Werte abspeichern kann.
Eine Variable kann aber immer nur Werte eines Datentyps aufnehmen (mit Aus-
nahme der unions). Dies liegt daran, daß unterschiedliche Daten (Buchstabe, ganz-
zahliger Wert, Gleitkommawert) unterschiedlich viel Speicher benötigen. Auch die
Codierung der Werte in Binärdarstellung für die Ablage im RAM ist für die einzel-
nen Datentypen unterschiedlich. Aus diesem Grund gehört jede Variable einem
Datentyp an, der bei der Definition der Variablen vom Programmierer angegeben
wird.
int var1; // Deklaration einer Variablen für ganzzahlige Werte
double var2; // Deklaration einer Variablen für Gleitkommawerte
char var3; // Deklaration einer Variablen für Zeichen
var1 = 3; // Zuweisung einer ganzzahligen Konstanten
var2 = 3.14; // Zuweisung einer Gleitkommakonstanten
var3 = 'c'; // Zuweisung einer Zeichenkonstanten

Verweise
Siehe Abschnitt, Kategorie Variablen und Datentypen.

Anweisungen ;
Der eigentliche Code des Programms. Die Anweisungen werden vom Compiler in
Maschinenbefehle umgesetzt, die vom Prozessor des Computers bei Ausführung des
Programms nacheinander abgearbeitet werden. Anweisungen enden stets mit einem
Semikolon.
● Anweisungen dürfen nur innerhalb der Anweisungsblöcke von Funktionen
stehen.
● Jede Programmanweisung muß mit einem Semikolon abgeschlossen werden.
● Mehrere Anweisungen können – durch Semikolons getrennt – in einer Zeile
stehen.
● Außer Anweisungen werden auch Deklarationen mit einem Semikolon abge-
schlossen.

22
Typische Komponenten von C/C++-Programmen

var1 = 3 * var2; // Zuweisung eines Wertes


// an eine Variable
printf("Hallo"); // Aufruf einer Funktion
return 0; // Schlüsselwort zur Beendigung
// einer Funktion

Anweisungsblöcke {}
In C/C++ werden Anweisungen in Anweisungsblöcken zusammengefaßt. Ein
Anweisungsblock beginnt mit einer öffnenden geschweiften Klammer und endet
mit einer schließenden geschweiften Klammer.
Anweisungsblöcke können ineinander verschachtelt werden. Der äußerste Block ist
dabei stets der Definitionsblock einer Funktion. Innerhalb des Anweisungsblocks
der Funktion kann man weitere Blöcke definieren, beispielsweise zur Implemen-
tierung einer Schleife oder zur Verzweigung des Programmablaufs in Abhängigkeit
von einer if-Bedingung .
void func() // Funktion
{ // Anweisungsblock zu Schleife
long loop = 1;

while (loop <= 10) // Schleife und Schleifenbedingung


{ // Anweisungsblock zu Schleife
// Potenzen berechnen
printf("%d ^ %d = %f\n", loop, loop, pow(loop,loop));
loop++;
}
}

Funktionen
Funktionen unterstützen die Modularisierung des Quellcodes. Statt alle Anwei-
sungen in die main()-Funktion zu schreiben, kann man zusammengehörende Anwei-
sungen, die eine gemeinsame Aufgabe erfüllen, als Funktionen auslagern.
Eine Funktion verfügt über
● einen Anweisungsblock,
● eine Schnittstelle zu den anderen Teilen des Programms und
● einen Namen, über den die Funktion aufgerufen werden kann.
Die folgende Funktion vergleich() definiert zwei Parameter, denen beim Aufruf der
Funktion Werte übergeben werden können. Als Ergebnis liefert die Funktion mit-
tels des Schlüsselworts return einen ganzzahligen Wert zurück, der anzeigt, ob die
beiden übergebenen Werte gleich oder unterschiedlich sind.
Funktionsdefinition:
int vergleich (int parameter1, int parameter2)
{

23
Grundlagen

if (parameter1 == parameter2)
return 1;
else
return 0;
}
Funktionsaufruf:
int ergebnis;
int var = 25;

ergebnis = vergleich(23, var); // weist ergebnis den Wert 0 zu

Verweise
Siehe Kapitel Funktionen.

Präprozessor-Direktiven #
Präprozessor-Direktiven sind spezielle Anweisungen an den Compiler (genauer
gesagt, den Präprozessor), die vor der eigentlichen Übersetzung des Programms in
Maschinencode ausgeführt werden. Präprozessor-Direktiven beginnen stets mit
einem »#« und stehen immer allein in einer Zeile.
Die wichtigste Präprozessor-Direktive lautet: #include. Sie dient dazu, den Inhalt
einer Textdatei in den Quelltext der aktuellen Datei einkopieren zu lassen. In
C/C++ werden selbst Anfänger gleich mit diesem Konzept konfrontiert, da man nur
auf diese Weise auf die Funktionen/Klassen der Standardbibliothek zugreifen kann.
Die Standardbibliotheken von C und C++ liegen als kompilierte LIB-Dateien vor
und enthalten die Definitionen einer Reihe von nützlichen Funktionen (und Klas-
sen). Um eine dieser Funktion in einem Programm aufrufen zu können, muß man
die Funktion zuvor beim Compiler bekanntmachen. Dies geschieht durch eine
Deklaration.
Um dem Programmierer die Tipparbeit für die Deklaration der Bibliothekselemente
zu ersparen, sieht der ANSI-Standard eine Reihe von Header-Dateien vor, in denen
die Deklarationen der Bibliothekselemente stehen. Jede Header-Datei ist einem spe-
ziellen Themengebiet gewidmet. Die Funktion printf() zur Textausgabe fällt bei-
spielsweise in den Bereich Ein- und Ausgabe, englisch Input/Output (IO), ihre
Deklaration ist in der Header-Datei stdio.h enthalten. Statt printf() und weitere
Funktionen zur Ein- und Ausgabe extra im Programm vorab zu deklarieren, genügt
es daher die Header-Datei stdio.h einzubinden:
#include <stdio.h>

24
Typische Komponenten von C/C++-Programmen

Kommentare /* */ und //
Kommentare sind Textpassagen, die vom Compiler ignoriert werden. Sie erlauben
dem Programmierer, Anmerkungen in den Quelltext aufzunehmen – meist zur
Erklärung des nebenstehenden oder nachfolgenden C/C++-Codes.
C
Kommentare beginnen in C mit der Zeichenkombination Schrägstrich – Stern »/*«
und enden mit der Zeichenkombination Stern – Schrägstrich »*/«. Die dazwischen-
stehenden Zeichen werden vom Compiler ignoriert. Dies gilt auch für das Zeilenen-
dezeichen, so daß sich Kommentare auch über mehrere Zeilen erstrecken dürfen.
Sie dürfen jedoch nach dem ANSI-Standard nicht verschachtelt werden. (Einige
Compiler erlauben optional die Verschachtelung von Kommentaren.)
/* Dies ist ein Kommentar, der sich über mehrere – genauer gesagt zwei -
Zeilen erstreckt */

/* Das folgende Programm gibt einen Gruß auf den */


/* Bildschirm Ihres Computers aus */
#include <stdio.h>
int main()
{
printf("Hallo!\n"); /* Aufruf einer Funktion */
return 0;
}
C++
In C++ kann die Auskommentierung auch durch doppelte Schrägstriche »//« erfol-
gen. Der nachfolgende Kommentar reicht bis zum Zeilenende. In C++ können beide
Konzepte zur Kommentierung unabhängig voneinander verwendet werden.
/* Das folgende Programm gibt einen Gruß auf den */
/* Bildschirm Ihres Computers aus */
#include <stdio.h>
int main()
{
printf("Hallo!\n"); // Aufruf einer Funktion
return 0;
}

Tip
In C++ bietet es sich an, innerhalb von Anweisungsblöcken nur //-Kommentare zu
verwenden und die Klammern /* und */ zum Auskommentieren größerer Blöcke
beim Debuggen einzusetzen.

25
Grundlagen

Größere Programme und Modularisierung


Beschreibung
Beim Aufsetzen größerer Programme empfiehlt es sich, den Code zu modularisieren, statt
diesen Anweisung für Anweisung untereinander in die main()-Funktion zu schreiben.
Die Modularisierung und Strukturierung des Codes sieht so aus, daß man
– einerseits Anweisungen und Code in Form von Funktionen und Klassen (nur C++) organi-
siert,
– andererseits den Quelltext selbst auf mehrere Dateien verteilt.

Aufteilung in Funktionen und Klassen


Größere Programmieraufgaben löst man üblicherweise, indem man Teilaufgaben
formuliert und diese in Form eigener Funktionen löst. Ein Programm, das zwei
Daten einliest, auf der Grundlage der Daten eine Berechnung ausführt und dann
das Ergebnis ausgibt, könnte drei Teilaufgaben definieren:
● Daten einlesen
● Berechnung durchführen
● Daten ausgeben
Für jede dieser Teilaufgaben könnte man eine eigene Funktion definieren (wobei
man für die Ein- und Ausgabe in einfachen Fällen auch direkt die entsprechenden
Funktionen der Laufzeitbibliothek verwenden kann).
Die Aufteilung in Funktionen hat den Vorteil, daß
● der Quelltext übersichtlicher ist,
● der Quelltext einfacher zu debuggen und zu warten ist.
Letzeres gilt insbesondere, wenn eine der Teilaufgaben mehrfach auszuführen ist.
Statt jedes Mal die zugehörigen Anweisungen einzutippen, ruft man nur die ent-
sprechende Funktion auf. Der Code wird nur einmal – in der Funktionsdefinition –
aufgesetzt. Stellt sich heraus, daß die Funktion fehlerhaft ist oder erweitert werden
muß, kann dies zentral in der Funktionsdefinition geschehen.
In C++ kann Code nicht nur in Funktionen, sondern auch in Klassen (Datentypen,
in denen Variablen und Funktionen zusammengefaßt werden) organisiert werden.

Aufteilung in mehrere Quelltextdateien


Umfangreichen Code kann man auf mehrere Quelltextdateien verteilen. Dies ist
beispielsweise angebracht, wenn man eine Sammlung von nützlichen Funktionen in
einer eigenen Datei verwahren will (meist der erste Schritt zu einer eigenen Biblio-
thek), oder wenn man zu mehreren an einem größeren Programmprojekt arbeitet.
Aufgabe des Compilers und Linkers ist es dabei, die einzelnen Quelltextdateien zu
einem Programm zusammenzufassen.

26
Größere Programme und Modularisierung

Alle Quelltextdateien, die zusammen in einem Schritt vom Compiler übersetzt und
zu einer Objektdatei kompiliert werden, bezeichnet man als Modul oder Überset-
zungseinheit. Eine Übersetzungseinheit besteht aus einer Implementierungsdatei
(Extension .c oder .cpp) und allen Quelltextdateien, deren Inhalt direkt oder indi-
rekt per #include-Anweisung eingebunden werden.

Beispiel
Für ein Programm, das zwei Zahlen von der Tastatur einliest und sowohl das Pro-
dukt als auch den Mittelwert der beiden Zahlen berechnet und ausgibt, könnte
man beispielsweise zwei spezielle Funktionen zur Berechnung des Produkts und des
Mittelwerts aufsetzen und diese dann in der main()-Funktion aufrufen.
(Für zwei so simple Berechnungen wie das Produkt und den Mittelwert zweier Zah-
len, würde man in der Praxis allerdings keine eigene Funktion aufsetzen. Doch geht
es hier nur darum, das Prinzip der Modularisierung zu verdeutlichen.)
#include <stdio.h>

int produkt_berechnen(int z1, int z2) {


int ergebnis;

ergebnis = z1 * z2; /* Produkt berechnen */


return ergebnis; /* Ergebnis zurückliefern */
}

double mittelwert_berechnen(int z1, int z2) {


double ergebnis;

ergebnis = (z1 + z2)/2.0; /* Mittelwert berechnen */


return ergebnis; /* Ergebnis zurückliefern */
}

int main(int argc, char **argv)


{
/* Variablen deklarieren */
int zahl1, zahl2;
int produkt;
double mittelwert;

/* Zahlenwerte einlesen */
printf("Geben Sie zwei Zahlen zwischen 0 und 100 ein: \n\n");
scanf("%d %d", &zahl1, &zahl2);
fflush(stdin);

/* Ergebnisse berechnen */
produkt = produkt_berechnen(zahl1, zahl2);
mittelwert = mittelwert_berechnen(zahl1, zahl2);

27
Grundlagen

/* Ergebnisse ausgeben */
puts("\n");
printf("Produkt = %d\n", produkt);
printf("Mittelwert = %f\n", mittelwert);

return 0;
}

Verweise
Siehe Abschnitt zur Sprache für detailliertere Informationen zu Funktionen und
Klassen.

Objektorientiertes Programmieren
Objektorientiert zu programmieren bedeutet nicht einfach, sich die Annehmlich-
keiten von C++ gegenüber C zunutze zu machen oder die Klassenbibliotheken statt
der C-Bibliotheken zu benutzen. In diesem strengeren Sinne kann man das folgende
Programmbeispiel, in dem statt der C-Funktion printf() die Klasseninstanz cout
und der überladene <<-Operator verwendet werden, nicht als objektorientiert pro-
grammiert bezeichnen.

Beispiel
/* Das erste C++-Programm. */
#include <iostream>
using namespace std;

int main() {
cout << "Hello world!" << endl;
return 0;
}
Objektorientierte Programmierung beginnt eigentlich erst da, wo Klassen definiert
und die wichtigen Konzepte der Kapselung und des Polymorphismus sinnvoll einge-
setzt werden, und sie rechtfertigt sich vor allem dort, wo Klassenbibliotheken ent-
stehen, die sich leicht und sicher verwenden lassen.
Letztendlich laufen alle wesentlichen Konzepte der objektorientierten Program-
mierung darauf hinaus, den Prozeß der Programmentwicklung zu beschleunigen,
sei es durch
● die Wiederverwertbarkeit bereits implementierter Codes,
● schnellere Entwicklung von Datentypen durch Vererbung und Polymorphis-
mus,

28
Verwendung der Standardbibliotheken

● geringere Fehleranfälligkeit durch Kapselung oder


● eine bessere Lesbarkeit der Programme, dank der objektorientierten Sichtweise.
Wo diese Kriterien nicht greifen, spricht nichts gegen eine Implementierung in C,
wobei der Verzicht auf die objektorientierten Konzepte eine geringere Codegröße
und bessere Laufzeiten mit sich bringt.

Verweise
Siehe Kapitel über Klassen.

Verwendung der Standardbibliotheken


#include

Beschreibung
Zu C und C++ gehört eine umfangreiche Sammlung von Funktionen und Klassen, die der Bewäl-
tigung der wichtigsten Programmieraufgaben dienen – etwa der Ein- und Ausgabe von Daten,
der Programmierung mit Zeichenketten (Text), der Verwendung mathematischer Funktionen
wie Sinus, Kosinus, Potenz, etc.

Anwendung
C/C++ verfügt über einen recht kleinen Satz von Schlüsselwörtern, etlichen Opera-
toren und einer äußerst umfangreichen Sammlung von Syntaxregeln, die vorschrei-
ben, wie man Schlüsselwörter, Operatoren und selbst definierte Bezeichner zu
korrekten C/C++-Programmen verknüpft.
Das Potential dieser Sprachelemente und -regeln ist enorm, doch wäre die Entwick-
lung selbst einfachster Programme allein mit diesen Sprachelementen eine mühsame
Angelegenheit, denn selbst für elementarste Programmieraufgaben bieten diese
Sprachelemente keine Unterstützung. So müßte man
● zum Kopieren von Zeichenketten (sprich Textpassagen) Schleifen program-
mieren, in denen die Zeichenfolgen Zeichen für Zeichen kopiert werden,
● zur Berechnung des Sinus einer Zahl sich zuerst in einem Lehrbuch der Mathe-
matik darüber informieren, wie man den Sinus einer Zahl durch Berechnung
einer trigonometrischen Reihe annähern kann,
● für Ein- und Ausgaben auf Betriebssystemebene programmieren.

29
Grundlagen

Voraussehende Programmierer werden diese häufig wiederkehrenden Programmier-


aufgaben in Form von eigenen Funktionen implementieren, damit sie – etwa bei der
Berechnung des nächsten Sinus – nicht mehr die ganze Berechnung ausführen
müssen, sondern nur noch die entsprechende Funktion aufrufen müssen.
Klevere Programmierer wissen, daß genau dies für die wichtigsten Programmierauf-
gaben bereits geschehen ist. Bevor Sie jedoch eine dieser Funktionen (für C++ auch
Klassen) aufrufen und verwenden können, müssen Sie
● sich informieren, welche Funktion / Klasse Ihr Problem lösen könnte (siehe
Referenz der Laufzeitbibliotheken)
● sich informieren, wie die Funktion / Klasse verwendet wird (siehe Referenz der
Laufzeitbibliotheken). Für Funktionen ist es beispielsweise wichtig, welche
Argumente man der Funktion beim Aufruf übergibt und welchen Ergebniswert
die Funktion zurückliefert.
● dem Compiler, der Ihren Programmquelltext übersetzt, die Funktion (Klasse)
bekanntmachen.
Die Präprozessor-Direktive #include dient dazu, den Inhalt einer Datei in den
Quelltext einkopieren zu lassen. In C/C++ werden selbst Anfänger gleich mit
diesem Konzept konfrontiert, da man nur auf diese Weise auf die Funktionen/Klas-
sen der Standardbibliothek zugreifen kann. Die Standardbibliotheken von C und
C++ liegen als kompilierte LIB-Dateien vor und enthalten die Definitionen einer
Reihe von nützlichen Funktionen (und Klassen). Um eine dieser Funktion in einem
Programm aufrufen zu können, muß man die Funktion zuvor per Deklaration beim
Compiler bekanntmachen.
Um dem Programmierer die Tipparbeit zu ersparen, sieht der ANSI-Standard eine
Reihe von Header-Dateien vor, in denen die Deklarationen der Bibliothekselemente
stehen. Jede Header-Datei ist einem speziellen Themengebiet gewidmet. Die Funk-
tion printf() zur Textausgabe fällt beispielsweise in den Bereich Ein- und Ausgabe,
englisch Input/Output (IO), ihre Deklaration ist in der Header-Datei stdio.h ent-
halten. Statt printf() und weitere Funktionen zur Ein- und Ausgabe extra im
Programm vorab zu deklarieren, genügt es daher die Header-Datei stdio.h einzu-
binden:
#include <stdio.h>

Warnung
Gemäß ANSI-C lauten alle Header-Dateien für die C-Laufzeitbibliothek auf .h aus.
Gemäß ANSI-C++ haben die Header-Dateien dagegen keine Extension und den
alten C-Headern wird der Buchstabe c vorangestellt (cstdio statt stdio.h). Zudem
sind alle Bibliothekselemente in dem Namensbereich std deklariert. Die korrekte
Einbindung der Header-Dateien in C++, beispielsweise der Header-Datei iostream
mit den Stream-Klassen zur Ein- und Ausgabe, sähe damit wie folgt aus:

30
Ein- und Ausgabe

#include <iostream>
using namespace std;
Einige Compiler unterstützen derzeit aber auch noch ältere Versionen von iostream
oder haben die Stream-Klassen nicht im Namensbereich std deklariert. In solchen
Fällen muß man sich notgedrungen nach der vom Compiler vorgegebenen Syntax
richten, meist:
#include <iostream.h>
oder
#include <iostream>

Ein- und Ausgabe


printf() / scanf()
cout / cin

Beschreibung
Um mit dem Anwender interagieren zu können, muß ein Programm in der Lage sein, Informa-
tionen und Daten vom Anwender entgegenzunehmen und selbst Daten und Informationen über
den Bildschirm auszugeben.

Anwendung
Im Unterschied zu Sprachen wie Fortran oder Basic besitzt die Sprache C keine
eigenen Sprachelemente zur Ein- oder Ausgabe. Dies bedeutet nicht, daß mit C-
oder C++-Programmen keine E/A-Operationen durchgeführt werden können. Man
muß nur statt eines Schlüsselworts der Sprache eine passende Funktion der Lauf-
zeitbibliothek aufrufen.
In C sind dies vor allem die Funktionen
● printf() für die Ausgabe auf die Konsole (Bildschirm)
● scanf() für das Einlesen von Tastatur.
In C++ bedient man sich der Klassen
● cout (Ausgabe auf Konsole) und
● cin (Einlesen von Tastatur)
und der Stream-Operatoren << und >>.

31
Grundlagen

Warnung
Die oben beschriebenen Funktionen und Klassen sind gemäß ANSI Teil der Stan-
dardbibliotheken von C/C++ und daher stets verfügbar. Der Austausch von Infor-
mationen zwischen Anwender und Programm über diese Funktionen und Klassen
ist allerdings auf Konsolenprogramme beschränkt. Programme mit grafischer
Benutzeroberfläche (GUI), die unter Windows, X-Windows oder OSF Motif laufen,
verwenden andere Möglichkeiten der Ein- und Ausgabe, die durch spezielle APIs
(Sammlungen von Funktionen und Klassen für bestimmte Programmieraufgaben)
unterstützt und implementiert werden.

Beispiele
Ein- und Ausgabe unter C:
#include <stdio.h>

int main()
{
int zahl1, zahl2;

/* Daten einlesen */
printf("Geben Sie zwei Zahlen zwischen 0 und 100 ein: \n\n");
scanf("%d %d", &zahl1, &zahl2);
fflush(stdin);

/* Daten ausgeben */
puts("\n");
printf("1. Zahl = %d\n", zahl1);
printf("2. Zahl = %d\n", zahl2);
printf("Produkt = %d\n", zahl1 * zahl2);
return 0;
}
Ein- und Ausgabe unter C++:
#include <iostream>
using namespace std;

int main()
{
int zahl1, zahl2;

/* Daten einlesen */
cout << "Geben Sie zwei Zahlen zwischen 0 und 100 ein: \n\n";
cin >> zahl1 >> zahl2;

/* Daten ausgeben */
cout << endl;
cout << "1. Zahl = " << zahl1 << endl;
cout << "2. Zahl = " << zahl2 << endl;

32
Programmfluß

cout << "Produkt = " << zahl1 * zahl2 << endl;


return 0;
}

Programmfluß
C/C++-Programme bestehen aus einer Ansammlung von Deklarationen und Defini-
tionen. Anweisungen findet man nur in Funktionen (in C++ auch in den Methoden
(Elementfunktionen) von Klassen). Damit stellt sich die Frage, mit welcher Anwei-
sung die Ausführung eines Programmes beginnt.
● Jedes C/C++-Programm beginnt mit der Hauptfunktion main(), die im Quell-
text des Programms definiert sein muß.
● Die Anweisungen in der main()-Funktion werden nacheinander ausgeführt.
● Durch Aufruf einer Funktion aus einer anderen Funktion heraus, beispielswei-
se auch aus main(), kann der Programmfluß gesteuert und der Quellcode durch
Aufteilung auf mehrere Funktionen modularisiert werden.
● Innerhalb einer Funktion kann der Programmfluß durch Verzweigungen (if,
switch) und Schleifen (for, while) gesteuert werden.

Warnung
Leser, die mit C/C++ für Windows programmieren wollen, seien darauf hingewie-
sen, daß Windows-Programme statt der main()-Funktion die Funktion WinMain()
verwenden. Je nach verwendetem Compiler und Klassenbibliothek kann WinMain()
selbst wieder durch eine andere Funktion (beispielsweise OwlMain() für Borland C++
mit OWL) oder eine Klasseninstanz (beispielsweise ein globales Objekt der MFC-
Klasse CWinApp in Visual C++) ersetzt sein.
Konsolenprogramme, die unter Windows ausgeführt werden (sprich im Fenster der
MS-DOS-Eingabeaufforderung ablaufen und über keine eigene Windows-Oberflä-
che verfügen), verwenden aber wie reine DOS- oder UNIX-Programme die main()-
Funktion.

Verweise
Siehe die Anschnitte zu Programmsteuerung, Funktionen, Exception-Behandlung.

33
Grundlagen

Programmerstellung
Beschreibung
Um aus einem in C/C++ formulierten Programmquelltext ein ausführbares Programm zu
machen, muß man es kompilieren. Bei der Kompilation wird der Programmquelltext vom Com-
piler in Maschinencode umgewandelt. In Zusammenarbeit mit dem Linker wird aus diesem
Maschinencode eine ausführbare Datei (unter Windows mit der Extension .exe) erzeugt, die
allerdings nur auf bestimmten Plattformen (Kombination aus Prozessor und Betriebssystem,
beispielsweise Intel-kompatibler Prozessor und Windows 95-Betriebssystem) ausgeführt
werden kann.

Anwendung
Die Erstellung eines Programmes ist natürlich nicht mit der Eingabe des Quelltextes
in einen Editor abgeschlossen. Bevor ein Programm ausgeführt werden kann, muß
es in maschinenlesbaren Code umgewandelt werden. Besteht ein Programm aus
mehreren Modulen, müssen diese zusammengebunden werden. Diese Aufgaben
übernehmen der Compiler und der Linker.
1. Quelltext in Editor eingeben. Dies kann prinzipiell in jedem ASCII-Texteditor
geschehen. PC-Compiler verfügen meist über eine integrierte Entwicklungsum-
gebung (IDE) mit eigenem Editor, der mehr Unterstützung bei der Programmer-
stellung bietet.
2. Header-Dateien einkopieren. Zu Beginn der Kompilation wird der Quelltext mit-
tels der #include-Direktive aufgeführter Header-Dateien in den Quelltext der Pro-
grammdatei kopiert.
3. Quelltextdateien kompilieren. Der Compiler übersetzt dann den Quelltext in ma-
schinenlesbaren Objektcode. Der Objektcode ist meist an eine bestimmte Umge-
bung (Computerkonfiguration) angepaßt und nicht zwischen unterschiedlichen
Umgebungen portierbar. Syntaktische Fehler im Programm werden vom Compi-
ler angezeigt und müssen korrigiert werden.
4. Objektcode-Dateien (.obj) und Bibliotheken (.lib) zusammenbinden. Besteht ein
Programm aus mehreren Quelltextdateien, werden diese vom Compiler einzeln in
Objektcode übersetzt. Dem Linker obliegt dann die Aufgabe, diese Objektcode-
Dateien sowie den Objektcode der benutzten Bibliotheksfunktionen in eine Pro-
grammdatei (.exe unter Windows) zusammenzubinden.
5. Debuggen. Nach dem Kompilieren und Linken liegt ein ausführbares, aber selten
ein korrektes Programm vor. Bezüglich lauffähigen Programmen unterscheidet
man Laufzeitfehler, die sich meist durch Programmabstürze oder Endlosschleifen
äußern, und logische Fehler, wenn das Programm zwar läuft, aber nicht seinen
Zweck erfüllt. Zum Aufspüren dieser Fehler verwendet man üblicherweise einen
Debugger, mit dessen Hilfe man das Programm schrittweise ausführen und kon-
trollieren kann.

34
Programmerstellung

Ablauf der Programmerstellung

Die gängigsten Compiler

Der GNU-Compiler
Der GNU-Compiler ist ein frei verfügbarer Compiler, den man kostenlos aus dem
Internet beziehen kann ([Link] Den GNU-Compiler gibt es
für UNIX wie für Windows.
Etwas unbequem für Windows-Anwender ist, daß der GNU-Compiler über keine
integrierte Entwicklungsumgebung verfügt, und man daher den Compiler explizit
aus der MS-DOS-Eingabeaufforderung heraus aufrufen muß.
1. Setzen Sie Ihren Quelltext mit einem beliebigen ASCII-Editor auf, und speichern
Sie die Datei.
2. Sofern Sie das /bin-Verzeichnis des Compilers in Ihren Pfad eingetragen haben, so
daß der Compiler gcc oder g++ von überall aufrufbar ist, wechseln Sie in das
Verzeichnis, in dem die Quelltextdatei steht.
3. Rufen Sie den C++-Compiler mit dem Dateinamen der Quelltextdatei auf:
g++ [Link]
oder
gcc quelltext.c
für den Aufruf des reinen C-Compilers.
Das fertige Programm lautet [Link] ([Link] unter Unix) und kann direkt ausgeführt
werden.

35
Grundlagen

Wenn Sie möchten, können Sie auch einen expliziten Namen für die ausführbare
Datei angeben.
g++ [Link] -o progname
Programme, die aus mehreren Modulen bestehen, erstellen Sie durch Auflistung
aller beteiligten Quelldateien (#include-Dateien werden nicht aufgeführt).
gcc [Link] [Link] -o progname
Wenn Sie dem Compiler irgendwelche Optionen übergeben wollen (beispielsweise -
ansi für strikt ANSI-kompatiblen Code oder -c für Kompilieren ohne zu Linken),
setzen Sie diese hinter den Dateinamen.
gcc [Link] -ansi -c
Für die Erstellung der Windows-Programme müssen verschiedene Bibliotheken
explizit mit eingebunden werden:
gcc [Link] -lkernel32 -luser32 -lgdi32
Welche weiteren Bibliotheken unter Umständen aufgenommen werden müssen, ent-
nehmen Sie der Compiler-Dokumentation.

Warnung
Die neueste Version des GNU-Compilers heißt jetzt egcs.

Der Borland C++-Compiler


In der IDE (integrierten Entwicklungsumgebung) des Borland C++-Compilers wer-
den Programme in Form von Projekten verwaltet. Konsolenanwendungen, die nur
aus einer Datei bestehen, können zwar ohne Projektverwaltung erstellt werden,
doch warum sollte man die angebotenen Möglichkeiten nicht nutzen.
1. Legen Sie ein neues Projekt an (Befehl Datei/Neu/Projekt für BorlandC++ 5.0, un-
ter 4.5 befand sich der Befehl noch im Menü Projekt). Es erscheint der Target Ex-
pert, in dem Sie angeben können, welche Art von Anwendung Sie erstellen wollen.
2. Geben Sie das Projektverzeichnis und einen Namen für die ausführbare Datei an.
Wählen Sie als Zieltyp Anwendung, als Umgebung Win32 und als Zielmodell Konsole
(oder als Umgebung DOS, wenn Sie noch mit einem Win16-Betriebssystem arbei-
ten). Die weiteren Einstellungen werden für Sie angepaßt, achten Sie aber darauf,
daß die OWL nicht eingebunden wird.
3. Öffnen Sie eine neue Quelltextdatei. Klicken Sie im erscheinenden Projektfenster
auf den Knoten der .cpp-Datei. (Wurden weitere Knoten angelegt (.rc, .def) kön-
nen Sie diese mit den Befehlen des Kontextmenüs löschen). Es erscheint ein
Editorfenster für die Quelltextdatei.
4. Geben Sie Ihren Quelltext ein und sichern Sie.

36
Programmerstellung

5. Rufen Sie den Compiler auf (Befehl Projekt/Projekt neu kompilieren für Bor-
landC++ 5.0).
6. Führen Sie das Programm aus (Befehl Debug/Ausführen für BorlandC++ 5.0). Unter
Win32 läuft das Programm in einem MS-DOS-Fenster ab, das sofort wieder
verschwindet, nachdem das Programm beendet wurde. Um dies zu verhindern,
können Sie die Beispielprogramme um einen Aufruf der Funktion getchar() vor
der return-Anweisung von main() erweitern. Das Programm wartet dann auf eine
Tastatureingabe, und das DOS-Fenster bleibt sichtbar.
Die Einstellungen für den Compiler und Linker werden in entsprechenden Dialog-
feldern gesetzt (Befehl Optionen/Projekt für BorlandC++ 5.0).
Zur Erstellung von Windows-Programmen wählen Sie im Target Expert als Zieltyp
Anwendung, als Umgebung Win32 und als Zielmodell GUI (statt Konsole). Achten Sie
darauf, daß keine zusätzliche Klassenbibliothek (OWL, OCF, MFC, etc.) eingebun-
den wird, da in diesem Buch nur reine API-Programme beschrieben sind.

Der C++-Builder
Der C++Builder von Borland arbeitet ebenfalls mit einer Projektverwaltung. Wäh-
rend der C++Builder 1.0 die Projekte jedoch noch einzeln verwaltete, gibt es in der
Version 3.0 nun auch die Möglichkeit, mehrere zusammengehörende Projekte
zusammen in einer Projektgruppe zu verwalten (analog den Arbeitsbereichen in
Visual C++).
1. Legen Sie ein neues Konsolen-Projekt an (Befehl Datei/Neu für C++Builder 3.0). Es
erscheint ein mehrseitiges Dialogfenster, in dem Sie zur Seite Neu wechseln.
2. Doppelklicken Sie auf das Symbol Konsolen-Experte (Textbildschirm-Anwen-
dung für 1.0).
3. Es erscheint direkt der Quelltexteditor des C++Builders mit einer extra Seite für
Ihren Quelltext. Speichern Sie Projekt und Quelltext (Befehl Datei/Alles spei-
chern).

4. Geben Sie Ihren Quelltext ein – entweder indem Sie ihn in das vorgegebene Gerüst
einpassen oder indem Sie das vorgegebene Gerüst zuvor löschen und dann Ihren
Text eintippen.
5. Führen Sie das Programm aus (Befehl Start/Start). Unter Win32 läuft das Pro-
gramm in einem MS-DOS-Fenster ab, das sofort wieder verschwindet, nachdem
das Programm beendet wurde. Um dies zu verhindern, können Sie die Beispielpro-
gramme um einen Aufruf der Funktion getchar() vor der return-Anweisung von
main() erweitern. Das Programm wartet dann auf eine Tastatureingabe, und das
DOS-Fenster bleibt sichtbar.

37
Grundlagen

Die Einstellungen für den Compiler und Linker werden in entsprechenden Dialog-
feldern gesetzt (Befehl Optionen/Projekt für C++Builder 1.0 oder Projekt/Optionen
für 3.0).
Zur Erstellung von Windows-Programmen doppelklicken Sie im Schritt 1 auf das
Symbol Anwendung statt auf Konsolen-Experte.

Warnung
Wenn Sie mit dem C++Builder 3 arbeiten, müssen Sie in Ihre Konsolenanwendun-
gen unter Umständen auch die Header-Datei <condefs.h> aufnehmen.

Tip
Der große Vorzug des C++-Builders liegt in der RAD-Umgebung zur Entwicklung
von Windows-Programmen. RAD bedeutet Rapid Application Development und
steht für die visuelle, komponentenbasierte Erstellung von Programmen.

Der Visual C++-Compiler


Auch der Visual C++-Compiler von Microsoft arbeitet mit einer Projektverwaltung.
Zusätzlich werden in Visual C++ Projekte in Arbeitsbereichen verwaltet (auf diese
Weise können beispielsweise die Projekte für eine Windows-Anwendung und
etwaige unterstützende DLLs und LIBs zusammen in einem Arbeitsbereich verwal-
tet werden).
1. Legen Sie ein neues Konsolen-Projekt an (Befehl Datei/Neu ab Visual C++ 5.0). Es
erscheint ein mehrseitiges Dialogfenster, in dem Sie zur Seite Projekte wechseln.
2. Geben Sie einen Projektnamen ein, wählen Sie den Pfad aus, unter dem das Ver-
zeichnis für die Quelldateien des Projekts eingerichtet wird, aktivieren Sie die Op-
tion Neuen Arbeitsbereich erstellen und doppelklicken Sie dann auf das Symbol
Win32-Konsolenanwendung. (In Visual C++ 6 erscheint daraufhin ein Dialogfenster,
in dem Sie neben einem leeren Projekt auch Projekte mit Datei und Grundgerüst
erstellen lassen können. Die nachfolgenden Schritte 3 und 4 erübrigen sich dann.)
3. Öffnen Sie eine neue Quelltextdatei (Befehl Datei/Neu, Seite Dateien ab Visual C++
5) Geben Sie einen Dateinamen ein, und doppelklicken Sie dann auf das Symbol
C++-Quellcodedatei.
4. Nachdem die Datei erstellt wurde, doppelklicken Sie im Arbeitsbereich-Fenster
(Seite Dateien) auf den gleichnamigen Knoten, um die Datei in ein Editorfenster
zu laden.
5. Geben Sie Ihren Quelltext ein und sichern Sie.
6. Kompilieren und linken Sie das Projekt (Befehl Erstellen/<ZIELDATEI> erstellen).
7. Führen Sie das Programm aus (Befehl Erstellen/Ausführen von <ZIELDATEI>).

38
Programmerstellung

Die Einstellungen für den Compiler und Linker werden in entsprechenden Dialog-
feldern gesetzt (Befehl Projekt/Einstellungen ab VisualC++ 5.0).
Zur Erstellung von Windows-Programmen doppelklicken Sie im Schritt 1 auf das
Symbol Win32-Anwendung statt auf Win32-Konsolenanwendung.

39
Zeichensatz

Sprachkonzepte und Syntax

Elemente der Sprache

Zeichensatz
Beschreibung
Man unterscheidet zwischen zwei Zeichensätzen:
– Dem Basiszeichensatz, den jeder ANSI-C/C++-Compiler zur Aufsetzung des Programmcodes
bereitstellt.
– Dem Ziel- oder Umgebungszeichensatz, den das Programm bei der Ausführung verwendet,
etwa für Ein- und Ausgaben.

Der Basiszeichensatz
Der Basiszeichensatz, den jeder C/C++-Compiler versteht und in dessen Zeichen der
Programmquelltext aufgesetzt wird, enthält die folgenden Zeichen:

a b c d e f g h i j k l m n o p q r s t
u v w x y z
A B C D E F G H I J K L M N O P Q R S T
U V W X Y Z
0 1 2 3 4 5 6 7 8 9
_ { } [ ] # ( ) < > % : ; . ? * + - / ^
& | ~ ! = , \ " '

sowie:

Leerzeichen Neue Seite (FF)


Horizontaler Tabulator (HT) Neue Zeile (NL)
Vertikaler Tabulator (VT)

41
Sprachkonzepte und Syntax

Quell- und Zielzeichensatz


Der Zielzeichensatz ist compilerspezifisch. Compiler, die unter Windows laufen,
verwenden derzeit üblicherweise den ANSI-Zeichensatz von Windows, dessen erste
128 Zeichen den Zeichen des traditionellen ASCII-Zeichensatzes entsprechen (siehe
Anhang). In Zukunft wird sich wohl UNICODE durchsetzen (das bereits von
Windows NT 4.0 unterstützt wird).
Auf die Zeichen dieses Zeichensatzes können Sie in Kommentaren und Zeichen-
bzw. String-Literalen zurückgreifen.
In Zeichen- und String-Literalen kann man darüber hinaus folgende Escape-Se-
quenzen verwenden:

Zeichen Escape-Sequenz
Neue Zeile NL (LF) \n
Horizontaler Tabulator HT \t
Vertikaler Tabulator VT \v
Rücktaste BS \b
Wagenrücklauf CR \r
Seitenvorschub FF \f
Signalton BEL \a
Backslash \ \\
Fragezeichen ? \?
Hochkomma ' \'
Anführungszeichen " \"
Oktaler Code \ooo
Hexadezimaler Code \xhhh

Beispiele
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)


{
char kaempfer[100]; // in Bezeichnern sind Umlaute
// nicht erlaubt (nur Basiszeichensatz),
strcpy(kaempfer,"Hägar"); // in String-Literalen schon

printf("Es kämpft für Sie: %s\n", kaempfer);


return 0;
}

42
Trigraphsequenzen

Trigraphsequenzen
Beschreibung
Trigraphsequenzen sind Folgen von jeweils drei Zeichen, die als Ersatz für bestimmte Zeichen
des Basiszeichensatzes verwendet werden können.

Anwendung
Der Basiszeichensatz ist eng an die englische Sprache und die englische Tastaturbe-
legung geknüpft. Für Programmierer anderer Nationen kann die Eingabe bestimm-
ter Zeichen auf Grund ihrer landesspezifischen Tastaturbelegung unbequem, wenn
nicht sogar nur über ALT+ASCII-Code möglich sein. Der ANSI-Standard definiert
aus diesem Grund eine Reihe von Trigraphsequenzen, die vom Compiler zu Beginn
der Kompilation in die entsprechenden Zeichen des Basiszeichensatzes umgewan-
delt werden.

Synonym Bedeutung Synonym Bedeutung


??= # ??! |
??/ \ ??< {
??' ^ ??> }
??( [ ??- ~
??) ]

Tip
Für die deutsche Tastaturbelegung bedeuten die Trigraphsequenzen keine große
Erleichterung. Um den Programmcode lesbar zu gestalten, sollte man auf Trigraph-
sequenzen verzichten.

Beispiele
??=include <stdio.h>

int main(int argc, char **argv)


??<
printf("Hallo??/n");
return 0;
??>

Schlüsselwörter und Symbole


Beschreibung
C/C++ kennt eine Reihe von Schlüsselwörtern und Symbolen, die innerhalb der Sprache eine
feste Bedeutung haben.

43
Sprachkonzepte und Syntax

Schlüsselwörter
asm (nur C++) false (nur C++) sizeof
auto float static
bool (nur C++) for static_cast (nur C++)
break friend (nur C++) struct
case goto switch
catch (nur C++) if template (nur C++)
char inline (nur C++) this (nur C++)
class (nur C++) int throw (nur C++)
const long true (nur C++)
const_cast (nur C++) mutable (nur C++) try (nur C++)
continue namespace (nur C++) typedef
default new (nur C++) typeid (nur C++)
delete (nur C++) operator (nur C++) typename (nur C++)
do private (nur C++) union
double protected (nur C++) unsigned
dynamic_cast (nur C++) public (nur C++) using (nur C++)
else register virtual (nur C++)
enum reinterpret_cast (nur C++) void
explicit (nur C++) return volatile
export (nur C++) short wchar_t (nur C++)
extern signed while

Warnung
Schlüsselwörter dürfen nicht als Bezeichner für Variablen, Funktionen, etc. verwen-
det werden.

Symbole
C/C++ kennt eine erstaunliche Zahl an bedeutungstragenden Symbolen, wobei ein
Großteil auf die vielen Operatoren der Sprache fällt.

Symbol Kurzbeschreibung Symbol Kurzbeschreibung


; Abschluß einer Anweisung oder -- Dekrement
Deklaration
{ } Anweisungsblock definieren -> Elementverweis-Operator
[ ] Array-Definition . Punkt-Operator
[ ] Array-Indizierung * Zeigerdeklaration
( ) Typumwandlung * Dereferenzierungs-Operator

44
Schlüsselwörter und Symbole

Symbol Kurzbeschreibung Symbol Kurzbeschreibung


( ) Parameterliste von Funktionen == Test auf Gleichheit
... variable Parameterzahl < Kleiner als-Vergleich
= Zuweisung > Größer als-Vergleich
+ Addition <= Kleiner-gleich-Vergleich
+= Addition und Zuweisung => Größer-gleich-Vergleich
- Subtraktion << Bitweise Linksverschiebung
-= Subtraktion und Zuweisung <<= Bitweise Linksverschiebung und
Zuweisung
* Multiplikation >> Bitweise Rechtsverschiebung
*= Multiplikation und Zuweisung >>= Bitweise Rechtsverschiebung und
Zuweisung
/ Division ?: Bedingungsoperator
/= Division und Zuweisung ^ Bitweises exklusives ODER
% Modulo-Operator ^= Bitweises exklusives ODER und
Zuweisung
%= Modulo-Operator und | Bitweises ODER
Zuweisung
! Logische Verneinung |= Bitweises ODER und Zuweisung
!= Vergleich auf Ungleichheit || Logisches ODER
& Referenzdeklaration ~ Komplement
& unär: Adresse des Operanden : Klasseninitialisierer
& binär: bitweise UND-Ver- :: Bereichsoperator (nur C++)
knüpfung
&= Bitweise UND-Verknüpfung .* Dereferenzierung von Zeigern
und Zuweisung auf Klassenelemente (nur C++)
&& Logische UND-Verknüpfung ->* Dereferenzierung von Zeigern
auf Klassenelemente (nur C++)
, Sequentielle Auswertung # Zeichenkettenbildung
++ Inkrement ## Grundsymbolverbindung

Alternative Zeichen
Für Programmierer mit ungünstigen nationalen Tastaturbelegungen gibt es für
einige Symbole alternative Zeichenfolgen (ähnlich den Trigraphsequenzen).

Alternative für
<% { Anweisungsblock beginnen
%> } Anweisungsblock beenden
<: [ Array-Definition und -Indizierung

45
Sprachkonzepte und Syntax

Alternative für
:> ] Array-Definition und -Indizierung
%: # Zeichenkettenbildung
%:%: ## Grundsymbolverbindung
and && Logische UND-Verknüpfung
and_eq &= Bitweise UND-Verknüpfung und Zuweisung
bitand & Bitweise UND-Verknüpfung
bitor | Bitweises ODER
compl ~ Komplement
not ! Nicht-Operator, Verneinung
not_eq != vergleicht zwei arithmetische Operanden auf Ungleichheit
or || Logisches ODER
or_eq |= Bitweises ODER und Zuweisung des Ergebnisses
xor ^ Bitweises exklusives ODER
xor_eq ^= Bitweises exklusives ODER und

Eigene Bezeichner: Definition und Deklaration


Beschreibung
Nur mit den Schlüsselwörtern und Operatoren der Sprache C/C++ kann man keine Programme
schreiben. C/C++ erlaubt daher die Einführung eigener Elemente in ein Programm. Alle vom
Programmierer eingeführten Elemente müssen deklariert und definiert werden.

Anwendung
Die wichtigsten Elemente, die ein Programmierer in ein Programm einführen kann,
sind:
● Variablen, um Daten zwischenzuspeichern,
● eigene Datentypen, um die Verwaltung der Daten zu organisieren und zu ver-
einfachen (einschließlich der Definition von Klassen),
● Funktionen, um zusammengehörige Anweisungen zusammenzufassen und den
Quelltext zu modularisieren.

Warnung
Die beiden Begriffe Deklaration und Definition werden häufig in etwas nachlässi-
gem Sprachgebrauch synonym gebraucht, auch wenn sie eigentlich Unterschied-
liches bedeuten.

46
Eigene Bezeichner: Definition und Deklaration

Deklaration
Deklaration bedeutet, dem Compiler einen Namen (Bezeichner) einer Variablen,
Funktion, Klasse, eines Templates, Datentyps oder Sprungmarke (Label) bekannt-
zumachen. Neben dem Namen des neuen Elements enthält die Deklaration bereits
alle nötigen Informationen, die den Compiler in die Lage versetzen die ordnungs-
gemäße Verwendung des Elements im Programmquelltext zu kontrollieren, und
Anweisungen, in denen das Element verwendet wird, in Maschinencode zu über-
setzen.
● Mit der Deklaration einer Variablen wird ihr Name, ihr Typ, die Speicher-
klasse und die Sichtbarkeit des Bezeichners festgelegt.
● Bei der Deklaration einer Funktion wird ihr Name, ihr Rückgabewert, die
Liste der Parameter und die Sichtbarkeit festgelegt.
● Mit einer Deklaration geht keine Speicherreservierung einher.
● Eine Variablendeklaration ist automatisch auch eine Definition, es sei denn,
die Deklaration ist als extern gekennzeichnet und enthält keine explizite Initia-
lisierung, oder es wird ein statisches Element einer Klasse deklariert.

Definition
Erst durch die Definition stellt der Compiler Speicherplatz für ein Element zur Ver-
fügung.
● Für Variablen wird in diesem Speicher der Wert der Variablen abgelegt.
● Für Funktionen wird in diesem Speicher der Code der Funktion abgelegt.
● Die Zuordnung von Namen zu Speicherbereichen muß eindeutig sein, d. h., ein
Name kann nicht gleichzeitig auf zwei verschiedene Speicherbereiche weisen.
In C bedeutet dies, daß innerhalb eines Gültigkeitsbereiches jeder Bezeichner nur
einmal definiert verwendet werden kann.
In C++ können, dank der Möglichkeit der Überladung, Bezeichner von Funktionen
und Operatoren innerhalb eines Gültigkeitsbereiches gleichzeitig in mehreren Defi-
nitionen benutzt werden. (Der Compiler löst dies, indem er die Namen um eine
codierte Form der Parameter oder Operanden erweitert, so daß jedem erweiterten
Namen wieder genau ein Speicherbereich zukommt.)

Verweise
Siehe Gültigkeitsbereiche, Sichtbarkeit, Lebensdauer

47
Sprachkonzepte und Syntax

Variablen und Datentypen

Variablen und Datentypen


Beschreibung
Ganz egal, welche Art von Programm Sie schreiben: Die Hauptaufgabe eines Programmes
besteht immer darin, Daten zu verarbeiten. Während das Programm abläuft, werden diese
Daten an verschiedenen Stellen im Arbeitsspeicher abgelegt. Um auf die Daten zugreifen zu
können, ohne sich mit Speicheradressen herumärgern zu müssen, werden Variablen benutzt.

Variablen
Eine Variable ist ein Name für einen Speicherbereich, in den ein Datenobjekt abge-
legt werden kann (beispielsweise eine ganze Zahl, eine Gleitkommazahl, eine Zei-
chenkette, etc.). Über den Namen der Variablen kann auf den Speicherbereich
zugegriffen werden, um die sich dort befindenden Daten zu lesen oder Daten dort-
hin zu schreiben. Der Compiler legt zu diesem Zweck eine Symboltabelle an, in der
zu jedem Variablenname die Anfangsadresse des zugehörigen Speicherbereichs ver-
merkt ist. Bei der Kompilation kann er dann jedes Vorkommen eines Variablenna-
mens durch die passende Adresse ersetzen. Für das Anlegen dieser Symboltabelle ist
es aber notwendig, daß jede Variable vor ihrer Verwendung deklariert wird, bei-
spielsweise:
int erste_Zahl;
Die wichtigste Angabe bei der Deklaration ist, neben dem Namen der Variablen,
der Datentyp.

Datentypen
Je nach Art der Daten, die in einer Variablen abgelegt werden können, unterschei-
det man verschiedene Datentypen, beispielsweise:
● int für ganze Zahlen
● double für reelle Zahlen (auch Gleitkommazahlen genannt)
● char für Zeichen (Buchstaben, Ziffern, Sonderzeichen)
● bool für Boolesche Variablen, die einen Wahrheitswert annehmen können
(true, false)
Die Datentypen bestimmen
● die interne Darstellung der Werte der Variablen im Rechner. (Bedenken Sie,
daß alle Daten im Speicher als eine Folge von Nullen und Einsen dargestellt

48
Variablen und Datentypen

werden müssen. Die Codierung eines Zeichens in eine Bitfolge erfolgt dabei
nach anderen Regeln als die Codierung einer ganzen Zahl oder einer Gleit-
kommazahl),
● die Größe des Speicherbereichs. (Eine Gleitkommazahl benötigt mehr Speicher
als ein einzelnes Zeichen, und eine Strukturvariable benötigt meist mehr Spei-
cher als eine Gleitkommazahl),
● den Wertebereich. (Dieser ergibt sich letztendlich aus der Größe des Speicher-
bereichs und der Art der Codierung),
● die Operationen, die auf den Werten des Datentyps ausgeführt werden können.
(Beispielsweise kann man ganze Zahlen addieren, nicht aber Zeichenketten).
C/C++ unterscheiden zwischen elementaren Datentypen, die in der Sprache veran-
kert sind (int, float, double, char, wchar_t und bool für C++), und zusammengesetz-
ten Datentypen, die vom Programmierer definiert werden (Aufzählungen, Arrays,
Strukturen und Klassen in C++).
Nach ihren gemeinsamen Eigenschaften und Einsatzgebieten bei der Programmier-
ung kann man die Datentypen weiter klassifizieren:
● Integrale Typen. Der Datentyp bool, die Datentypen char und wchar_t, die
Datentypen int und long, Aufzählungen (enum), Bitfelder. Integrale Datentypen
sind als Datentyp für switch-Variablen erlaubt.
● Arithmetische Typen. Alle integralen Typen plus die Datentypen float, double
und long double. Sie sind als Operanden für die arithmetischen Operatoren
(+, --, *, /) erlaubt.
● Skalare Typen. Arithmetische Datentypen und Zeiger. Sie sind als Schleifen-
variablen für for erlaubt.

char
class wchar_t
struct short
union int
array long

Integer- Bitfelder
typen
Objekttypen
Aufzählungen
Arithmetische
Typen

float
Skalare Gleitkomma- double
Typen typen long double

Zeiger-
typen

49
Sprachkonzepte und Syntax

Die elementaren Datentypen


short, int, long
float, double, long double
char, wchar_t
bool

Beschreibung
Die elementaren Datentypen sind Datentypen, die fest in Form von Schlüsselworten in der
Sprache verankert sind.

Anwendung
Mit Hilfe der elementaren Datentypen kann der Programmierer Variablen für die
verschiedenen Arten von Daten deklarieren (Zahlen, Zeichen, Wahrheitswerte).
Darüber hinaus kann man auf der Grundlage der elementaren Datentypen eigene
zusammengesetzte Datentypen definieren.
Die Programmiersprache C/C++ kennt folgende elementare Datentypen:
● die Datentypen short, int und long für Ganzzahlwerte
● die Datentypen float, double und long double für Gleitkommazahlen
● die Datentypen char und wchar_t für Zeichen (Buchstaben, Ziffern, Satzzei-
chen, etc.)
● den Datentyp bool für Wahrheitswerte (nur C++)
Der Wertebereich der Datentypen – also der Bereich von Werten, die man Varia-
blen dieses Datentyps zuweisen kann – hängt von der Anzahl Bytes ab, die der
Compiler für eine Variable dieses Datentyps im Speicher bereitstellt.
Bis auf den Datentyp bool sind alle diese Datentypen vorzeichenbehaftet, d. h., man
kann den Variablen diesen Typs negative wie positive Werte zuweisen. Durch Vor-
anstellung des Schlüsselworts unsigned kann man festlegen, daß für den Datentyp
nur positive Werte erlaubt sind. Das Schlüsselwort signed gibt explizit an, daß ein
Datentyp vorzeichenbehaftet ist, und ist üblicherweise redundant, da die Daten-
typen ehedem vorzeichenbehaftet sind. Einzige Ausnahme: der Datentyp char.

Warnung
Für den Datentyp char ist gemäß ANSI nicht festgelegt, ob der Datentyp vorzei-
chenbehaftet ist oder nicht. Im Zweifelsfall empfiehlt sich bei der Variablendekla-
ration die explizite Deklaration als signed char oder unsigned char.

Bezeichner Bytes Wertebereich*


bool 1 false, true
signed char 1 -128 bis 127

50
Speicherbelegung der Integer-Typen

Bezeichner Bytes Wertebereich*


unsigned char 1 0 bis 255
wchar_t 2 0 bis 65.535
int signed int 4 -[Link] bis [Link]
unsigned int 4 0 bis [Link]
short, short int 2 -32.768 bis 32.767
unsigned short int 2 0 bis 65.535
long, long int 4 -[Link] bis [Link]
signed long int
unsigned long int 4 0 bis [Link]
float 4 ca. -3.4E +38 bis 3.4E+38
double 8 ca. -1.8E +308 bis 1.8E+308
long double 10 ca. -3.4E +4932 bis 3.4 E+4932

* Die angegebenen Wertebereiche sind für 32-Bit-Systeme typische Wertebereiche.


Es ist allerdings zu beachten, daß die Wertebereiche von der Codierung der Werte
in Binärdarstellungen abhängt. Diese Binärcodierung wird allerdings nicht bis ins
Detail vom ANSI-Standard vorgegeben und ist daher implementierungsspezifisch –
hängt also letztendlich vom jeweiligen Compiler ab.

Tip
Die minimalen und maximalen Werte für die einzelnen Datentypen sind in den
ANSI-C Headerdateien limits.h und float.h bzw. für C++ in den Spezialisierungen
der Template-Klasse numeric_limits (aus limits) festgelegt und können von dort
abgefragt werden.

Speicherbelegung der Integer-Typen


short, int, long

Beschreibung
Vorzeichenbehaftete Integer-Werte werden üblicherweise gemäß dem 2er-Komplement binär-
codiert. Das erste Bit von links codiert dabei das Vorzeichen: 0 steht für positive Zahlen, 1 für
negative Zahlen. Multiplikationen mit -1 entsprechen der Invertierung aller Bits mit an-
schließender Addition von 1.

51
Sprachkonzepte und Syntax

R|∑ a ⋅ 2n −1

|
i
für an = 0
∂ ba , K , a g := S
i
i=0
n 0
||∑ a ⋅ 2 - 2
n −1
i n
für an = 1
T i=0
i

Speicherbelegung

int i = 3;
00000000 00000000 00000000 00000011

&i

Speicherbelegung der Gleitkommatypen


float, double, long double

Beschreibung
Gleitkommazahlen werden durch zwei Werte codiert, von denen der eine Mantisse, der andere
Exponent genannt wird. In dieser sogenannten Exponential-Schreibweise wird z. B. die Zahl
54.123 folgendermaßen aussehen: 0,54123*10e4. Die Zahl 0,54123 ist in dem Beispiel die (nor-
malisierte) Mantisse, die Zahl 4 der Exponent zur Basis 10 (Compiler verwenden allerdings
üblicherweise die Basis 2).
Der ANSI-Standard schreibt nicht explizit vor, wie Gleitkommazahlen zu codieren sind, die Codie-
rung muß aber dem von ANSI vorgegebenen Gleitkommamodell folgen, und die Charakteristika
der Codierung müssen in den Konstanten aus der Header-Datei float.h festgehalten werden
(numeric_limits<float> und numeric_limits<double> aus der Header-Datei limits für C++).

x = s ⋅ be ⋅
LM∑ f
p
OP
⋅ b− k , emin ≤ e ≤ emax
N
k=1
k
Q
s = Vorzeichen
b = Basis des Exponenten
e = Exponent
p = Anzahl Stellen der Mantisse (bestimmt die Genauigkeit)
fk = Ziffer der Mantisse

52
Vorzeichen integraler Datenypen

Speicherbelegung

Vorzeichenbit (1)

Exponent (8) Mantisse (23) = single precision

Vorzeichenbit (1)

Exponent (11) Mantisse (52) = double precision

Vorzeichen integraler Datenypen


Beschreibung
Durch Angabe der Schlüsselwörter unsigned beziehungsweise signed kann man bei der Varia-
blendeklaration festlegen, ob in dem Datentyp das Vorzeichen codiert sein soll oder nicht. Ent-
sprechend verschiebt sich der Wertebereich des Datentyps.

Anwendung
Wertebereichsverschiebungen durch signed/unsigned:

Datentyp signed unsigned


char -128 bis 127 0 bis 255
short -32768 bis 32767 0 bis 65535
int -[Link] bis 0 bis [Link]
[Link]
long -[Link] bis 0 bis [Link]
[Link]

Warnung
● Variablen von unsigned Datentypen können nicht überlaufen. Wird versucht,
Werte außerhalb ihres Gültigkeitsbereichs an sie zuzuweisen, wird automa-
tisch der Modulo-Operator auf den Wert angewandt.
● Beachten Sie, daß in C/C++ die Datentypen von Operanden intern angeglichen
werden (Arithmetische Konvertierungen). Vergleicht man beispielsweise einen
signed-Wert mit einem unsigned-Wert, wird der signed-Wert als unsigned-Wert
interpretiert. Auf diese Weise kann ein kleiner negativer Wert zu einem großen
positiven Wert werden. (Beachten Sie insbesondere, daß der Rückgabewert des
sizeof-Operators unsigned ist.)

53
Sprachkonzepte und Syntax

● Liegt eine char-Variable mit Vorzeichen im Bereich von -128 bis 127, liegt eine
entsprechende char-Variable ohne Vorzeichen im Bereich zwischen 0 und 255.
Dies kann bei der Portierung unter Umständen zu Problemen führen. Man
kann dem durch die Voranstellung eines der Qualifizierer signed oder unsigned
vorbeugen.

Variablendeklaration
datentyp variablenname;

Beschreibung
Variablen sind vom Programmierer eingeführte Bezeichner, denen Werte zugewiesen werden
können. Welche Werte einer Variablen zugewiesen werden können, hängt vom Datentyp der
Variablen ab. Der Compiler verbindet die Variable mit einem Speicherbereich, in dem der
jeweils aktuelle Wert der Variablen abgespeichert wird.

Anwendung
Variablen sind für ein Programm wie ein Zwischenspeicher, in dem Daten abgelegt
und bei Bedarf wieder hervorgeholt und weiter verarbeitet werden können. Eine
Variable wird durch eine Deklaration eingeführt und ist grundsätzlich vom Ort
ihrer Deklaration ab verfügbar.

Warnung
Die Verfügbarkeit einer Variablen hängt von mehreren Faktoren ab: dem Ort der
Deklaration, den bei der Deklaration verwendeten Spezifizierern, dem Gültigkeits-
bereich und der Lebensdauer der Variablen.

54
Variablendeklaration

Syntax
datentyp variablenname;
datentyp var1, var2, var2;
● datentyp: Bei der Deklaration wird zuerst der Datentyp durch Verwendung
des entsprechenden Typbezeichners angegeben. Erlaubt sind sowohl elemen-
tare wie auch zuvor definierte, zusammengesetzte Datentypen.
● variablenname: Durch mindestens ein Leerzeichen getrennt, folgt auf den Typ-
bezeichner der Name der Variablen. Es können mehrere Variablen gleichzeitig
deklariert werden, wobei die Bezeichner durch Kommata getrennt werden.

Initialisierung
Variablen kann man direkt im Zuge der Deklaration einen Wert zuweisen.
int monate = 12;

Spezifizierer
spezifizierer datentyp variablenname;
Die Variablendeklaration kann durch eine Reihe von speziellen Schlüsselwörtern
näher spezifiziert werden:

Schlüsselwort const Legt fest, daß der Variablen nach der Initialisierung
(Wertzuweisung im Zuge der Deklaration) kein anderer
Wert mehr zugewiesen werden kann.
const int monate = 12;
Schlüsselwort volatile Teilt dem Compiler mit, daß diese Variable nicht etwaigen
Optimierungen im Zuge der Kompilation zum Opfer fallen
darf.
volatile double var;
Speicherklassenspezifizierer Zur expliziten Vergabe einer Speicherklasse. Zusammen
mit dem Ort der Deklaration legt die Speicherklasse die
Sichtbarkeit und Lebensdauer der Variablen fest.
auto
extern
register
static

Speicherklasse auto
Das Schlüsselwort auto weist einer Variablen explizit die automatische Speicher-
klasse zu. Diese Speicherklassenangabe kann nur innerhalb von Blockbereichen
(und für Parameter) verwendet werden und ist im übrigen überflüssig, da lokale
Variablen standardmäßig auto sind.

55
Sprachkonzepte und Syntax

Der Speicherplatz für automatische Variablen wird bei Abarbeitung des Blocks, in
dem sie deklariert werden, auf dem Stack erzeugt, und beim Verlassen des Blocks
wieder freigegeben.

Speicherklasse register
Grundsätzlich entspricht der Spezifizierer register dem Schlüsselwort auto. Es teilt
dem Compiler darüber hinaus aber mit, daß auf die derart deklarierte Variable so
schnell wie möglich zugegriffen werden soll.
Für PCs bedeutet dies, daß die Variablen in die Register des Prozessors geladen
werden sollen. Der Compiler braucht dies jedoch nicht zu tun.
In C kann im Gegensatz zu C++ die Adresse eines Objekts, das mit register dekla-
riert worden ist, nicht mehr ermittelt werden, gleichgültig, ob dieses Objekt sich in
einem Prozessorregister befindet oder nicht. In C gibt es daher keine Zeiger auf
Register-Variablen.
Grundsätzlich sollte man heutzutage die Aufteilung der Register den mittlerweile
sehr leistungsfähigen Compilern überlassen und auf die Spezifikation des Schlüssel-
worts register verzichten.

Speicherklasse static
Grundsätzlich impliziert das Schlüsselwort static lokale Gültigkeit und einmalige
Allokation (letzteres bedeutet, daß statische Elemente nicht auf dem Stack angelegt
werden).
Damit ergeben sich drei wichtige Einsatzbereiche:
Bezeichner, die global deklariert sind, haben üblicherweise externe Bindung (das
heißt, in Programmen, die aus mehreren Modulen zusammengelinkt werden,
bezeichnen sie in allen Modulen das gleiche Objekt). Werden Sie als static dekla-
riert, sind sie nur innerhalb ihres Moduls gültig.
Lokale Variablen von Funktionen werden bei Aufruf der Funktion neu allokiert
und bei Verlassen der Funktion zerstört. Wird eine solche Variable als static dekla-
riert, wird nur beim ersten Aufruf der Funktion Speicherplatz für die Variable
reserviert und gegebenenfalls initialisiert. Zusätzlich endet ihre Lebensdauer erst
mit dem Programm und nicht der Funktion. Die Sichtbarkeit bleibt unverändert.
Klassen können nicht als static deklariert werden, aber Klassenelemente (siehe
Kategorie Klassen).
● Ein statisches Klassen-Datenelement erfüllt ähnliche Aufgaben wie eine globa-
le Variable. Ein solches Datenelement wird nur einmal initialisiert (und zwar
außerhalb der Klasse!) und dann von allen Instanzen der Klasse geteilt. (Übli-
cherweise hat jede Instanz der Klasse natürlich eine eigene Kopie der Klassen-
elemente.)

56
Variablendeklaration

● Eine statische Klassenmethode ist eine Methode, die nur auf statische Klassen-
elemente zugreifen kann und wie ein statisches Datenelement von allen Instan-
zen der Klasse oder über den Klassennamen aufgerufen werden kann.
Deklarationen von Funktionsparametern und Funktionsdeklarationen in einem
Blockbereich können nicht als static spezifiziert werden.

Speicherklasse, extern
Mit dem Spezifizierer extern kann einem Objekt oder einer Funktion externe Bin-
dung zugewiesen werden. Externe Bindung bedeutet dabei, daß alle Vorkommen
eines Bezeichners mit externer Bindung sich auf ein und dasselbe Objekt beziehen.
Bei der internen Bindung beziehen sich nur die Bezeichner aus einer Datei auf ein
und dasselbe Objekt. Bezeichner ohne Bindung identifizieren eindeutige Objekte.
● Objekte und Funktionen, die in einem Namensbereich oder global deklariert
sind, haben automatisch externe Bindung, es sei denn, sie wurden schon zuvor
mit einem anderen Speicherklassenspezifizierer deklariert. (In C++ haben zu-
dem auch globale Objekte, die als const deklariert sind, interne Bindung.)
● Klassenelemente und Funktionsparameter können nicht als extern deklariert
werden.
● Objektdefinitionen ohne gleichzeitige Initialisierung werden durch den Spezifi-
zierer als reine Deklaration gekennzeichnet. Auf diese Weise kann ein Objekt
mit externer Bindung in allen Modulen bekannt gemacht werden, ohne daß es
zu mehrfachen Definitionen kommt.
● C++ erlaubt die mehrfache Definition von Funktionen gleichen Namens, so-
weit sich diese durch Anzahl und Typen ihrer Parameter unterscheiden. Intern
wird diese Namensmehrdeutigkeit vom Compiler so aufgelöst, daß er den ein-
zelnen Funktionsdefinitionen neue Namen zuordnet, in die die Parameter in
codierter Form mit aufgenommen sind. Dies ist nicht immer erwünscht, bei-
spielsweise, wenn Funktionen aus kompiliertem C-Code benutzt werden. Die
Namenserweiterung kann daher durch den Bindungs-Spezifizierer extern "C"
unterdrückt werden.

Beispiele
short int woche;
char zeichen;
int tag, monat;
int jahr = 1998; // Initialisierung
const int monate = 12; // konstante Variable

Verweise
Siehe Gültigkeitsbereiche, Sichtbarkeit, Lebensdauer

57
Sprachkonzepte und Syntax

Gültigkeitsbereiche
Beschreibung
In C/C++ wird jeder Variablen in Abhängigkeit davon, an welcher Stelle des Programms die
Variable deklariert wird, ein Gültigkeitsbereich zugeordnet.

Anwendung
Der Gültigkeitsbereich einer Variablen ist der Bereich eines Programms, in dem
eine Variable gültig ist. Variablen können nur innerhalb ihres Gültigkeitsbereichs
und nach ihrer Deklaration verwendet werden.

Tip
Diese automatische Vergabe von Gültigkeitsbereichen kann vom Programmierer
durch die Aufnahme bestimmter Speicherklassenspezifizierer in die Deklaration an
seine Bedürfnisse angepaßt werden.

Gültigkeitsbereiche
● Blockbereich: Variablen, die innerhalb eines Anweisungsblocks (abgegrenzt
durch die geschweiften Klammern {..}) deklariert werden, sind von lokaler
Gültigkeit. Sie sind nur innerhalb des Blocks bekannt und existieren nur so-
lange, wie der Block abgearbeitet wird. Der Compiler erzeugt diese Variablen
dynamisch. Nach der Beendigung des Blocks wird der Speicherplatz der loka-
len Variablen freigegeben. Damit ist auch ihr Wert verloren. Lokale Variablen
werden zumeist innerhalb von Funktionen deklariert.
C erlaubt Deklarationen nur zu Beginn eines Blocks, also vor irgendwelchen
Anweisungen. C++ erlaubt Deklarationen dagegen an jeder beliebigen Stelle
im Block (sogar in Schleifenheadern).
● Dateibereich: Variablen, die außerhalb jeden Anweisungsblocks, jeder Klasse
und jeden Namensbereiches deklariert werden, sind von globaler Gültigkeit
und können ab dem Punkt ihrer Deklaration benutzt werden. Sie haben globa-
le Lebensdauer, das heißt, sie existieren vom Start des Programms bis zu des-
sen Ende.
● Funktionsbereich: Dieser Bereich gilt nur für die Vergabe von Marken für die
goto-Anweisung , denn Marken dürfen nicht aus der Funktion, in der sie de-
klariert wurden, herausweisen.
● Klassenbereich (nur C++): Elemente von Klassen sind – mit Ausnahme stati-
scher Elemente – nur innerhalb ihrer Klasse gültig. Sie werden bei der Instanz-
bildung erzeugt und bei der Auflösung der Instanz zerstört.
● Namensbereiche (nur C++): In C++ ist es möglich, den globalen Gültigkeits-
bereich durch die Deklaration von Namensbereichen aufzuteilen. Die Dekla-

58
Namensbereiche

ration eines Namensbereiches faßt eine Reihe von Deklarationen in


geschweifte Klammern zusammen. Eingeleitet wird die Deklaration durch das
Schlüsselwort namespace.

Beispiel
#include <stdio.h>

namespace Spezielles // Deklarationen in Namensbereich


{
int var1;

class demo { // Deklarationen in Klassenbereich


int wert;
public:
demo(): wert(3) {}
};
}

void func(int param) // Deklarationen in Blockbereich


{
int var;
}

int var; // Deklarationen in Dateibereich

int main()
{
...
return 0;
}

Verweise
Siehe Namensbereiche
Siehe Sichtbarkeit, Lebensdauer

Namensbereiche
namespace bereichsname { }

Beschreibung
Mit Hilfe des Schlüsselwortes namespace kann der Programmierer den globalen Gültigkeitsbe-
reich (Dateibereich) in Unterbereiche aufteilen.

59
Sprachkonzepte und Syntax

Zudem können Deklarationen aus Namensbereichen gezielt in bestimmte Gültig-


keitsbereiche eingeführt werden (etwa in den Blockbereich einer Funktion oder
einen anderen Namensbereich).

Anwendung
Die Aufteilung des globalen Gültigkeitsbereichs ist vor allem für Programmierer
interessant, die mit anderen Programmierern zusammen an umfangreicheren Soft-
wareprojekten arbeiten. Würden in so einem Fall alle Programmierer ihre globalen
Variablen in einem gemeinsamen globalen Gültigkeitsbereich deklarieren, kann es
bei der Zusammenführung der Quelltextdateien zu einem Programm schnell zu
Fehlermeldungen des Linkers wegen mehreren globalen Variablen gleichen Namens
kommen. Durch die Einrichtung individueller Namensbereiche kann man dem
abhelfen.
Zudem steht es dem Programmierer, der Elemente aus einem Namensbereich ver-
wenden will, frei, diese bei Bedarf einzeln anzusprechen oder mit Hilfe des using-
Schlüsselwortes alle Deklarationen aus dem Namensbereich mit einer Anweisung in
seinen eigenen globalen Gültigkeitsbereich oder den Blockbereich einer speziellen
Funktion einzuführen.

Deklaration von Namensbereichen


namespace bezeichner
{
// Deklarationen
}
● Namensbereiche können nur im globalen Bereich oder innerhalb eines anderen
Namensbereiches deklariert werden.
● Namensbereichen, die ohne eigenen Bezeichner deklariert wurden, wird der
Bezeichner unique zugewiesen, der bei der Kompilation durch einen eindeuti-
gen Bezeichner ersetzt wird. Dieser Bezeichner ist in jeder Übersetzungseinheit
(Datei) verschieden. Die Deklaration eines Objektes im unbenannten Namens-
bereich kommt daher einer Deklaration als static im globalen Bereich gleich.
● Elemente eines Namensbereiches können direkt innerhalb der Deklaration des
Namensbereiches definiert werden oder außerhalb unter Verwendung des
Namensbereich-Bezeichners und des Bereichsoperators.

Namensbereiche verwenden
using namespace NameDesNamensbereichs;
Mit Hilfe des Schlüsselwortes using kann ein Namensbereich in einen anderen Gül-
tigkeitsbereich eingeführt werden. Danach sind alle in dem neu eingeführten
Namensbereich deklarierten Elemente auch in dem Gültigkeitsbereich bekannt, in
den der Namensbereich eingeführt wurde.

60
Namensbereiche

Nach Einführung des Namensbereichs kann man im umliegenden Gültigkeits-


bereich auf die Elemente aus dem Namensbereich direkt über den Bezeichner des
Elements (ohne Voranstellung des Namensbereichs) zugreifen.
● Gibt es im umliegenden Gültigkeitsbereich ein Element, das genauso heißt wie
eines der Elemente aus dem eingeführten Namensbereich, verdeckt das Ele-
ment aus dem umliegenden Gültigkeitsbereich das Element aus dem Namens-
bereich. Durch Voranstellung des Namensbereichs kann auf das Element des
Namensbereichs zugegriffen werden.
● Unbenannte Namensbereiche sind immer im umliegenden Namensbereich be-
kannt.
● Namensbereiche können nicht in Klassen, wohl aber in Methoden von Klassen
eingeführt werden.

Namensbereiche erweitern
namespace bezeichner {
// Deklarationen
}
namespace bezeichner {
// weitere Deklarationen
}
Namensbereiche können mehrfach deklariert werden, wobei nachfolgende Deklara-
tionen als Erweiterungen behandelt werden.
Auf diese Weise können Namensbereiche über Dateigrenzen hinweg deklariert, aus-
getauscht und erweitert werden.

Zugriff auf Elemente in Namensbereichen


Elemente, die in Namensbereichen deklariert sind, können außerhalb des Namens-
bereichs nicht einfach über den Namen, unter dem sie im Namensbereich deklariert
sind, aufgerufen werden. Entweder
● muß der vollständige Bezeichner (einschließlich des Namens des Namensbe-
reichs) verwendet werden, oder
● der Bezeichner wird durch eine using-Anweisung eingeführt. Dies entspricht ei-
ner Neudeklaration. Nach der Neudeklaration kann auf das Element des Na-
mensbereichs ohne Voranstellung des Namensbereichs zugegriffen werden.
Gibt es allerdings im umliegenden Gültigkeitsbereich bereits einen gleichlau-
tenden Bezeichner scheitert die Neudeklaration.
● der Namensbereich und alle in ihm enthaltenen Deklarationen werden durch
eine using-Anweisung eingeführt. Danach kann man auf die Elemente des Na-
mensbereichs ohne Voranstellung des Namensbereichs zugreifen. Es liegt dabei
jedoch keine Neudeklaration vor. Werden im umliegenden Gültigkeitsbereich
und im Namensbereich gleichlautende Bezeichner verwendet, verdecken die

61
Sprachkonzepte und Syntax

Bezeichner des umliegenden Gültigkeitsbereichs die Elemente aus dem Namens-


bereich. Durch vollständige Qualifizierung (Voranstellung des Namensbereichs
vor den Bezeichner) kann jedoch auch auf die verdeckten Elemente zugegriffen
werden.)

Synonyme
namespace Deklarationen_für_speziellen_Zweck
namespace Spez1 = Dekarationen_für_speziellen_Zweck
Für die Bezeichner von Namensbereichen können Synonyme eingeführt werden.
Für Namensbereiche mit extralangen Namen können so kürzere Aliase definiert
werden.

Beispiele
Das folgende Programm demonstriert die Definition und Einführung von Namens-
bereichen:
namespace A { // Definition eines Namensbereichs
int i = 1;
}
namespace B {
int i = 2;
using namespace A; // Einführung eines Namensbereichs
}

int main() {
//cout << i; // Fehler, da i nicht global deklariert
// und kein Namensbereich angeschaltet
cout << A::i; // ok, Zugriff über vollständigen Qualifizierer
using namespace A;
cout << i; // ok, liefert A::i
using namespace B;
//cout << i; // Fehler, kann A::i oder B::i sein
return 1;
}
Das zweite Beispiel zeigt Möglichkeiten und Fallstricke bei der Erweiterung von
Namensbereichen:
namespace demo {
int i = 1; // demo::i
void func1(int);
void func2(int);
class X {
int i = 2; // demo::X::i
};
}
namespace demo { // Erweiterung
//int i = 3; // Fehler: doppelte Definition

62
Sichtbarkeit und Verdeckung

void func1(float); // Überladung


void func2(int); // ok: Redeklaration
namespace {
int i = 4; // demo::unique::i
}
}

Verweise
Siehe Kapitel über Verwendung der Standardbibliotheken

Sichtbarkeit und Verdeckung


Beschreibung
Prinzipiell ist jedes per Deklaration eingeführte Element ab dem Ort der Deklaration in seinem
Gültigkeitsbereich sichtbar – kann also über seinen Namen angesprochen und benutzt werden.

Verdeckung
Wird ein und derselbe Bezeichner mehrfach benutzt, um Elemente in ineinander
verschachtelten Gültigkeitsbereichen zu deklarieren (beispielsweise für eine globale
Variable und eine gleichlautende lokale Variable in einer Funktion), verdeckt die
Variable des innersten Gültigkeitsbereichs alle Variablen der umschließenden Gül-
tigkeitsbereiche.
In C++ kann man auf verdeckte Variablen aus dem globalen Gültigkeitsbereich mit
Hilfe des Gültigkeitsbereichoperators weiterhin zugreifen:
● für globale Variablen aus dem Dateibereich stellt man dem Bezeichner einfach
den Operator voran ::var_name
● für Variablen aus Namensbereichen gibt man zusätzlich den Namensbereich
an: namensbereich::var_name
Zudem kann man in abgeleiteten Klassen auf verdeckte Elemente der Basisklassen
über den Gültigkeitsbereichoperator zugreifen: basisklasse::element.

Warnung
Die Mehrfachverwendung eines Bezeichners innerhalb eines Gültigkeitsbereichs ist
nur in Ausnahmefällen möglich:
● Klassen- und enum-Bezeichner können durch Bezeichner für Variablen, Funk-
tionen und enum-Elemente im gleichen Gültigkeitsbereich verdeckt werden.

63
Sprachkonzepte und Syntax

● Die Überladung von Funktionen in C++ beruht auf der Verwendung des glei-
chen Bezeichners für die Definition mehrerer Funktionen in einem Gültigkeits-
bereich. (Der Compiler löst die Namen intern anhand der Parameterliste auf.)

Beispiele
int wert = 1; // global deklariert
void func() {
int wert = 2; // lokal deklariert, verdeckt globales wert
cout << " wert = " << wert << endl; // Ausgabe: 2
cout << "::wert = " << ::wert << endl; // Ausgabe: 1
};

Lebensdauer
Beschreibung
Wenn Sie eine Variable definieren, erzeugt der Compiler für diese Variable ein Objekt im Spei-
cher (auf das Sie über den Namen der Variablen zugreifen können). In ähnlicher Weise werden
Objekte im Speicher erzeugt, wenn Sie dynamischen Speicher reservieren, wenn bei einem
Funktionsaufruf die Parameter eingerichtet werden, wenn Instanzen von Klassen gebildet
werden (wobei Klassenobjekte erst nach Aufruf des Konstruktors existieren).
Wie lange diese Objekte verfügbar und existent sind, hängt von verschiedenen Faktoren ab.

Anwendung
● Ort der Deklaration. Variablen (einschließlich der Instanzen von Klassen), die
in einem Blockbereich definiert werden, existieren nur bis zum Ende des
Blockbereichs und werden bei Verlassen des Blocks aufgelöst (liegt daran, daß
der Speicher für die Variablen auf dem Stack abgelegt wird). Variablen, die
global deklariert werden, existieren bis zum Programmende.
● Speicherklassenspezifizierer static. Für Variablen, die innerhalb eines Block-
bereichs als static deklariert werden, wird der Speicher nicht auf dem Stack
reserviert. Die Variablen existieren bis zum Programmende.
● Art der Speicherreservierung. Objekte, für die der Speicher dynamisch reser-
viert wird (mit malloc() oder new), wird der Speicher auf dem Heap reserviert
und wird erst freigegeben, wenn der Programmierer dies explizit fordert
(free() oder delete) oder das Programm beendet wird.

Verweise
Siehe Funktionen, Funktionen und der Stack

64
Zusammengesetzte Datentypen

Zusammengesetzte Datentypen

Zusammengesetzte Datentypen
Beschreibung
Mit den elementaren Datentypen ist bereits der Grundstock für die Datenverarbeitung in Pro-
grammen gelegt. Tatsächlich käme man sogar ohne die Möglichkeit zur Definition weiterer
Datentypen aus, doch die Programmierung würde sich dann in vielen Fällen äußerst mühsam
gestalten.
Aus diesem Grunde sieht C/C++ verschiedene Möglichkeiten zur Definition eigener Datentypen
vor. Bevor wir uns diese aber im einzelnen anschauen werden, sollte man sich noch einmal klar
machen, daß man mit der Definition eines neuen Datentyps nicht nur die eigenen Bedürfnisse,
sondern auch die Bedürfnisse des Compilers befriedigen muß.
Konkret bedeutet dies, daß der Compiler wissen muß, wie er für Variablen dieses Datentyps
Speicher belegen muß, wie die Werte der Variablen codiert und im Speicher abgelegt werden
sollen, welche Operationen auf den Variablen des Datentyps erlaubt sind und schließlich wie
Typkonvertierungen vorgenommen werden können.
Aus all diesen Anforderungen könnte man nun ablesen, daß die Möglichkeiten zur Definition
eigener Datentypen entweder sehr eingeschränkt oder mit sehr viel Arbeit verbunden sind. Nun
beides ist nicht der Fall. Der Trick dabei ist einfach, daß man die neuen selbst definierten
Datentypen aus den elementaren Datentypen ableitet.
Insgesamt stehen Ihnen folgende Möglichkeiten zur Definition eigener Datentypen zur Verfü-
gung:
– Definition eines Datentyps durch Aufzählung der Wertemenge des Datentyps (enum)
– Definition eines Datentyps durch Zusammenfassung mehrerer Variablen eines Datentyps
(Arrays)
– Definition eines Datentyps durch Zusammenfassung mehrerer Variablen verschiedener
Datentypen (Strukturen)
– Definition eines Datentyps durch Zusammenfassung mehrerer Variablen verschiedener
Datentypen, und durch Bereitstellung typspezifischer Funktionen und Operatoren (Klassen).
Dies ist die freieste und weitreichendste Form der Typdefinition.
Schließlich gibt es noch die Möglichkeit, Zeiger zu definieren, mit denen man direkt auf Spei-
cherbereiche zugreifen und Objekte im Speicher manipulieren kann.

65
Sprachkonzepte und Syntax

Aufzählungstypen
enum {element1, element2, ...};
enum typbezeichner {element1, element2, ...};

Beschreibung
Aufzählungstypen sind Datentypen, deren mögliche Werte durch explizite Aufzählung von Inte-
ger-Konstanten festgelegt werden. Die aufgeführten Werte können im wesentlichen wie im
umgebenden Gültigkeitsbereich definierte Konstanten verwendet werden.

Anwendung
Bei allen anderen Datentypen sind die Wertebereiche durch die interne Codierung
der Werte in Binärdarstellung vorgegeben. Welche Werte beispielsweise eine int-
Variable annehmen kann, hängt nicht von Ihnen, sondern von Ihrem Compiler ab.
Bestenfalls können Sie über Spezifizierer wie short, long oder unsigned auf den Wer-
tebereich einwirken.
Bei einem Aufzählungstyp können Sie durch explizite Auflistung selbst angeben,
welche Werte zum Wertebereich des neuen Aufzählungstyps gehören. Dies kann
einen Programmcode lesbarer und leichter verständlich machen. In C++ kommt
hinzu, daß der Compiler prüfen kann, daß Variablen eines Aufzählungstyps auch
wirklich nur Werte aus seinem Wertebereich zugewiesen werden.
Da intern alle Werte eines Aufzählungstyps durch Integer-Konstanten repräsentiert
werden, kann man Werte aus Aufzählungen beispielsweise auch in switch-Verzwei-
gungen verwenden.

Syntax
enum {element1, element2, ...};
enum typbezeichner {element1, element2, ...};
● elemente: Die in einem Aufzählungstyp definierten Elemente werden wie Inte-
ger-Konstanten behandelt. Damit die Konstanten nicht undefinierte Werte an-
nehmen, werden sie vom Compiler automatisch initialisiert. Nichtinitialisierte
Elemente bekommen dabei den Wert ihres Vorgängers +1 zugewiesen. Dem
ersten Element wird 0 zugewiesen. Mit Hilfe des Zuweisungsoperators kann
der Programmierer den Elementen selbst Werte zuordnen. Es sind allerdings
nur Integer-Werte erlaubt oder Werte, die als Integer-Werte interpretiert wer-
den können. Verschiedene Elemente dürfen gleiche Werte haben.
● typbezeichner: Wird ein typbezeichner spezifiziert, kommt dies einer Typdefini-
tion gleich. Später können dann Variablen dieses Typs definiert werden. In C
lautet der Typ enum typbezeichner, in C++ reicht einfach der typbezeichner.

66
Arrays

Variablendeklaration
enum {elem1 = 1, elem2 } var1, var2;
Oder
enum typbez {elem1 = 1, elem2 };
enum typbez var1, var2;

Wertzuweisung
var1 = elem2;
var1 = typbez(3);

Warnung
Der Compiler reserviert für enum-Variablen Speicher, der groß genug sein muß, um
alle Integer-Werte zwischen dem kleinsten und größten Wert des enum-Typs aufneh-
men zu können. Prinzipiell kann man enum-Variablen jeden Wert innerhalb dieses
Wertebereichs zuweisen, auch wenn der Wert nicht explizit in der Aufzählung
definiert ist (in C++ erfordert dies eine explizite Typumwandlung).

Beispiele
#include <stdio.h>
enum {ERROR_LESEN = 101,ERROR_SCHREIBEN = 102};

void fehlermeldung(int fehlernummer) {


switch(fehlermeldung) {
case ERROR_LESEN: /* Anweisungen */ break;
case ERROR_SCHREIBEN: /* Anweisungen */ break;
default: break;
}
}
int main() {
fehlermeldung(ERROR_NO_MEM);
return 0;
}

Arrays
typ feldname[groesse];

Beschreibung
Ein Array, auch Datenfeld oder Feld genannt, ist die Zusammenfassung von mehreren Daten
des gleichen Typs zu einer Variablen.

67
Sprachkonzepte und Syntax

Anwendung
Arrays ermöglichen Ihnen, eine (nahezu) beliebige Zahl von Variablen gleichen
Datentyps en bloc zu definieren:
int i[100];
Der Vorteil der Array-Deklaration liegt jedoch nicht nur in der eingesparten Tip-
parbeit. Die einzelnen Elemente eines Arrays werden im Speicher hintereinander, in
einem zusammenhängenden Block abgelegt. Dies bringt eine Reihe interessanter
Vorteile, beispielsweise die Möglichkeit, über einen Index auf einzelne Elemente im
Block zuzugreifen:
i[3] = i[2]+i[1];

Syntax
typ feldname[groesse];
● typ: Die Typangabe legt fest, aus welchen Elementen das Array gebildet wird,
und liefert zusammen mit der groesse Informationen über den Speicherplatzbe-
darf (groesse * sizeof(typ)).
Folgende Datentypen sind für Elemente eines Arrays nicht zulässig: Referen-
zen, Funktionen, abstrakte Klassen.
● feldname: Frei wählbarer Name für die Array-Variable. Array-Typen sind im-
mer an Variablen gebunden. Dies ist eine Besonderheit der Arrays.
● groesse: Die groesse legt die Anzahl der Elemente fest, aus denen das Array be-
steht. Als Größenangabe sind nur konstante Ausdrücke erlaubt, die größer
Null sind. Die Größenangabe kann auch weggelassen werden. In solch einem
Fall muß eine vollständige Deklaration nachfolgen, oder das Array muß bei
der Deklaration mit Hilfe einer Initialisierungsliste initialisiert werden. (Aus
der Anzahl der Initialisierungswerte wird dann die Dimension errechnet.)

Variablendeklaration
int feld[3]; // Array für drei int-Objekte
struct person leser[40]; // 40 Elemente vom
// Typ struct person
Oder
#define ANZAHL 400;
double feld[ANZAHL];

Initialisierung
Es ist möglich, bei der Definition eines Arrays Initialisierungen vorzunehmen. Dem
Namen des Arrays folgt dann das Gleichheitszeichen und in geschweifte Klammern
gefaßt die einzelnen Werte, die zugewiesen werden sollen.

68
Arrays

● Es ist nicht erforderlich, alle Elemente zu initialisieren. Elemente, die nicht


initialisiert worden sind, erhalten automatisch den Wert 0.
● Fehlt die Größenangabe, wird die Größe aus der Anzahl der Elemente errech-
net.
float werte[3] = { 2.34, 5.76 }; /* entspricht:
werte[0] = 2.34;
werte[1] = 5.76;
werte[2] = 0; */
float werte[] = { 2.34, 5.76 }; /* entspricht float werte[2] */

Zugriff auf Array-Elemente


Auf die einzelnen Elemente des Arrays wird über einen Index zugegriffen, der in
eckigen Klammern steht. Das erste Element eines Arrays hat immer den Index 0.
Das letzte Element hat den Index groesse – 1.
feld[0] = 13;
Oder
#define ARRAY_GROESSE 20
int array[ARRAY_GROESSE];
for (i=0; i < ARRAY_GROESSE; i++)
array[i] = i;

Warnung
Die Indizierung der Elemente im Array beginnt immer mit 0, weswegen beispiels-
weise die Indizes für ein Array, das als feld[20] deklariert ist, von 0 bis 19 laufen.
Der Zugriff über höhere Indizes ist möglich (der Compiler kontrolliert nicht die
Verwendung korrekter Indizes), führt aber fast ausnahmslos zu Laufzeitfehlern.
Wenn man sowohl die Arraygröße angibt als auch eine Initialisierungsliste defi-
niert, darf letztere nicht mehr Elemente enthalten als durch die Arraygröße festge-
legt.

Beispiele
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
#define MAX 100 // Anzahl der Elemente in Array

int main()
{
int feld[MAX]; // Array deklarieren
int i;

memset(feld, 0, sizeof(feld)); // Initialisieren des Arrays

69
Sprachkonzepte und Syntax

// Array ganz durchlaufen und Zufallswerte zuweisen


for (i = 0; i < MAX; i++)
{
feld[i] = rand() % 100;
}

// Array durchlaufen und Werte ausgeben


for (i = 0; i < MAX; i++)
{
printf("Element %d \t = %d\n", i, feld[i] );
}

return 0;
}

Verweise
Siehe Mehrdimensionale Arrays
Siehe Zeichenketten (Strings)

Mehrdimensionale Arrays
typ feldname[dim1][dim2];

Beschreibung
Zwei- oder mehrdimensionale Arrays sind Arrays, deren Elemente wiederum Arrays sind.
Auch mehrdimensionale Arrays werden nacheinander im Speicher abgelegt. Das Prinzip funk-
tioniert so, daß der letzte Index sich am schnellsten verändert. Die Elemente des Arrays
int matrix[3][2];
würden im Speicher also in folgender Reihenfolge abgelegt:
matrix[0][0]
matrix[0][1]
matrix[1][0]
matrix[1][1]
matrix[2][0]
matrix[2][1]

Anwendung
Mehrdimensionale Arrays werden am sinnvollsten dort eingesetzt, wo Daten ver-
waltet werden sollen, die von sich aus schon mehrdimensional organisiert sind, so
daß sich eine 1:1-Entsprechung zwischen der natürlichen Anordnung der Daten
und ihrer Abspeicherung im Array ergibt.

70
Mehrdimensionale Arrays

Ein Beispiel wären die Elemente einer zweidimensionalen Matrix, die sich wunder-
bar in einem zweidimensionalen Array verwalten lassen.

Syntax
typ feldname[dim1][dim2];
● typ: Die Typangabe legt fest, aus welchen Elementen das Array gebildet wird.
● feldname: Frei wählbarer Name für die Array-Variable.
● dim: Die Definition enthält so viele Paare eckiger Klammern mit Größenanga-
ben, wie das Array Dimensionen besitzt. Bei mehrdimensionalen Arrays kann
die erste eckige Klammer leer bleiben. Dies erklärt sich dadurch, daß ein
mehrdimensionales Array als ein einfaches Array angesehen wird, dessen Ele-
mente wiederum Arrays sind. Die Größe des Arrays darf später deklariert wer-
den, aber die Größe der Elemente muß bei der Deklaration feststehen.

Variablendeklaration
int feld[3][2];

Initialisierung
Mehrdimensionale Arrays können auf zwei Arten initialisiert werden. Entweder
wird für jede Komponente eine eigene Initialisierungsliste benutzt, die in
geschweifte Klammern eingeschlossen wird, oder jeder Komponenten des unterge-
ordneten Aggregattyps werden die Werte einfach der Reihe nach zugewiesen.
int matrix[][2] = { { 1, 2 },
{ 10, 20 },
{ 100, 200 } };
Oder
int matrix[3][2] = { 1, 2 , 10, 20, 100, 200 };

Zugriff auf Array-Elemente


Um auf ein Element eines mehrdimensionalen Arrays zuzugreifen, muß man für
jede Dimension einen Index angeben.
var = matrix[2][0];
Obige Anweisung greift auf das dritte Unterarray (Indizierung beginnt mit 0!) und
in dem Unterarray auf das erste Element zu (wäre im Beispiel aus dem Initialisie-
rungsabschnitt das Element mit dem Wert 100).

Beispiele
#include <stdio.h>
#define SPALTEN 10
#define ZEILEN 5

71
Sprachkonzepte und Syntax

int main() {
int x[ZEILEN][SPALTEN];
int i = 0;
int j = 0;

for (i = 0; i < ZEILEN; i++)


{
for (j = 0; j < SPALTEN; j++)
{
x[i][j] = 'a' + i;
}
}

for (i = 0; i < ZEILEN; i++)


{
for (j = 0; j < SPALTEN; j++)
{
printf("%c ",x[i][j]);
}
printf("\n");
}

return 0;
}
Ausgabe
a a a a a a a a a a
b b b b b b b b b b
c c c c c c c c c c
d d d d d d d d d d
e e e e e e e e e e

Verweise
Siehe Arrays

Zeichenketten (Strings)
charTyp str[groesse];

Beschreibung
Arrays bieten sich auch als Variablen für Zeichenketten (Strings) an. In diesem Fall sind die
Elemente des Arrays die Zeichen der Zeichenkette.

Anwendung

72
Zeichenketten (Strings)

ANSI C/C++ verwendet zur Repräsentation von Text die sogenannten ASCIIZ-
Strings. Dies sind Zeichenketten, die durch das Zeichen \0 abgeschlossen werden.
Variablen, die einen solchen Strig aufnehmen können, kann man auf verschiedene
Weise deklarieren:
● als Array mit Elementen eines char-Typs.
● als Zeiger auf einen char-Typ.
● als Instanz einer string-Klasse (nur C++).
Entscheidet man sich für ein Array, genießt man den Vorteil, daß zusammen mit
der Array-Deklaration auch gleich der Speicher für den String reserviert wird. Man
muß aber aufpassen, daß man der Array-Variablen keinen String zuweist, der aus
mehr Zeichen besteht als das Array reserviert hat.

Warnung
Beachten Sie zudem, daß ein String in C/C++ immer mit dem Zeichen \0 abge-
schlossen werden muß. Dieses Terminierungszeichen ist bei der Berechnung des
Speicherbedarfs mit einzurechnen.

Syntax
charTyp feldname[groesse];
● charTyp: Als Elementtyp wählt man in diesem Fall char, signed char, unsigned
char oder wchar_t.
● feldname: Frei wählbarer Name für die Array-Variable.
● dim: Anzahl der Zeichen, für die Speicher reserviert wird und die in dem
Array abgelegt werden können.

Initialisierung
char str[ ] = {'e', 'i', 'n', 's', '\0'}; // mit Initialisierungsliste
Oder
char str2[50] = "Dies ist ein String"; // mit String-Literal
wchar_t str3[10] = L"zwei"; // Wide Character-Zeichen (UNICODE)
Bei der Initialisierung mit String-Literalen wird das abschließende Nullterminie-
rungszeichen \0 automatisch durch den Compiler angehängt.

Zuweisung
Die Zuweisung mit Hilfe des Zuweisungsoperators ist nur bei der Initialisierung
möglich. Danach bedient man sich am besten der Funktionen der Laufzeitbiblio-
thek (C-Header-Datei string.h).
strcpy(str2, "Neuer Text"); // kopieren
strcat(str1, str2); // anhängen

73
Sprachkonzepte und Syntax

Zugriff auf einzelne Zeichen


str1[4] = 'c';

Beispiele
#include <stdio.h>
#include <string.h>

int main() {
char string1[] = "C und C++";
char string2[] = "C++ und C";
if(strcmp(string1, string2) > 0)
printf("%s ist groesser als %s\n",string1,string2);
else
printf("%s ist kleiner oder gleich %s\n", string1, string2);
return 0;
}
Ausgabe
C und C++ ist kleiner oder gleich C++ und C

Verweise
Siehe Arrays
Siehe Zeichenketten, C-Strings

Strukturen
struct typbezeichner
{
typ1 element1;
typ2 element2;
};

Beschreibung
Strukturen fassen mehrere Daten, die unterschiedlichen Datentypen angehören können, zu
einer Variablen zusammen. In C++ ist eine Struktur ein Sonderfall einer Klasse, in der alle Ele-
mente standardmäßig public sind.

Anwendung
Strukturen sind Datentypen, in denen mehrere Variablen verschiedener Datentypen
zusammengefaßt werden können. Die in der Struktur zusammengefaßten »Varia-
blen« bezeichnet man als Felder oder Elemente der Struktur. Der Vorteil dabei ist, daß
mehrere, logisch zusammengehörende Daten in einem Datentyp vereinigt werden
können.

74
Strukturen

Ein typisches Beispiel wäre die Definition von Variablen zum Abspeichern von
Vektoren. Für einen zweidimensionalen Vektor benötigt man zwei int-Werte für
die x- und die y-Koordinate. Diese als einzelne int-Variablen zu definieren, ist
unbequem und äußerst unübersichtlich:
int v1_x, v1_y; // erster Vektor
int v2_x, v2_y; // zweiter Vektor
Besser ist die Einführung eines Strukturtyps für Vektoren:
struct vektor {
int x;
int y;
};
struct vektor v1, v2;

Warnung
● Eine Struktur kann keine Variable ihres eigenen Typs als Element enthalten.
Zeiger oder Referenzen auf Variablen ihres eigenen Typs sind aber erlaubt.
● In C++ sind Strukturen Klassen mit public-Zugriff auf die Strukturelemente. In
C++ dürfen Strukturen daher auch Funktionen als Elemente enthalten.

Syntax
struct typbezeichner {
typ1 element1;
typ2 element2;
/* weitere Elemente */
};
● typbezeichner: Wird ein typbezeichner spezifiziert, kommt dies einer Typdefini-
tion gleich. Später können dann Variablen dieses Typs definiert werden. In C
lautet der Typ struct typbezeichner, in C++ reicht einfach der typbezeichner.
● typ element: Innerhalb der Klammern werden die Elemente der Struktur dekla-
riert.

Definition von Strukturvariablen


Strukturvariablen können entweder nach der Definition der Struktur mit Hilfe des
Typbezeichners definiert werden (vorausgesetzt ein Typbezeichner wurde angege-
ben) oder direkt im Zuge der Strukturdefinition.
struct person { /* Definition */ };
struct person leser;
person autor; // nur C++
struct person leser[40]; // 40 Elemente vom Typ struct peson
Oder
struct {
int x;

75
Sprachkonzepte und Syntax

int y;
float laenge;
} vektor1, vektor2;

Initialisierung
Strukturvariablen können bei ihrer Definition direkt initialisiert werden. Dazu wer-
den die Werte, mit denen die Strukturelemente initialisiert werden sollen, in
geschweiften Klammern aufgelistet und mittels des Zuweisungsoperators der Varia-
blen zugewiesen.
● Es ist nicht erforderlich, alle Elemente der Struktur zu initialisieren.
struct person {
char name[20];
int plz;
char ort[20];
char strasse[20];
};
struct person leser = {"Klaus Müller",
7652 , "Entenhausen", "Duckstr. "
};

Zugriff auf Strukturelemente


Es gibt zwei Möglichkeiten, um auf die Elemente einer Struktur zuzugreifen. Das
benutzte Verfahren hängt davon ab, ob man über eine Strukturvariable oder einen
Zeiger auf eine Struktur, auf die Elemente zugreift.
[Link]
strukturzeiger->strukturelement

Beispiele
struct person {
char name[20];
int plz;
char ort[20];
};
int main() {
struct person leser;
struct person *pleser;

pleser = &leser;
[Link] = 5100;

strcpy([Link], "Otte");
strcpy(pleser->ort, "Karlsbad");
printf("Leser: %s, PLZ: %d Ort: %s\",
[Link], [Link], [Link]);
printf("Leser: %s, PLZ: %d Ort: %s\",

76
Bitfelder

pleser->name, pleser->plz, pleser->ort);


return 0;
}

Bitfelder
struct typbezeichner
{
intTyp1 element1 : Zahl;
intTyp2 element2 : Zahl;
};

Beschreibung
Bitfelder sind besondere Elemente in Strukturtypen, für die man explizit angeben kann, wieviel
Bit für das Element benötigt werden.

Anwendung
Bitfelder werden benutzt, wenn Daten gespeichert werden sollen, die weniger als 1
Byte Speicherplatz benötigen. Hierzu gehören zum Beispiel 1 Bit große Flags, die
ausreichen, um Wahrheitswerte darzustellen. Nach der Typangabe und dem optio-
nalen Namen des Elements folgt ein Doppelpunkt. Daran schließt sich ein ganzzah-
liger Wert an, der bestimmt, wie viele Bits diesem Element zur Verfügung gestellt
werden sollen.
Bitfelder werden traditionell häufig zur Speichereinsparung eingesetzt. Dahinter
verbirgt sich die Idee, daß die Bits der Bitfelder hintereinander abgespeichert
werden, daß eine Struktur mit zwei Bitfeldern von 3 und 5 Bit Länge, also bei-
spielsweise ingesamt nur 8 aufeinanderfolgende Bits (1 Byte), belegen würde; ob
dem so ist, hängt allerdings vom Compiler ab. Deswegen und wegen des heute rela-
tiv billigen Arbeitsspeicher, ist von dem Einsatz von Bitfeldern zur Speichererspar-
nis eher abzuraten.

Warnung
● Ein einzelnes Bitfeld muß nach ANSI C immer den Datentyp int, signed int
oder unsigned int besitzen. C++ erlaubt dagegen jeden Typ, der als Integer
interpretierbar ist, also auch char, short, long und Aufzählungstypen.
● Für Bitfelder können keine Zeiger und Referenzen deklariert werden.
● Unbenannte Bitfelder der Größe 0 bewirken, daß das nächste Bitfeld in einer
neuen Allokationseinheit (meist int oder word) beginnt.

77
Sprachkonzepte und Syntax

Syntax
struct typbezeichner {
intTyp1 element1 : Zahl;
intTyp2 element2 : Zahl;
/* weitere Elemente */
};
● typbezeichner: Wird ein typbezeichner spezifiziert, kommt dies einer Typdefini-
tion gleich. Später können dann Variablen dieses Typs definiert werden. In C
lautet der Typ struct typbezeichner, in C++ reicht einfach der typbezeichner.
● typ element : zahl: Innerhalb der Klammern werden die Bitfelder deklariert.
Als Typ dürfen nur int-Typen verwendet werden. Auf den Elementnamen
folgt ein Doppelpunkt und die Angabe der Bits, die für das Bitfeld reserviert
werden sollen. Gibt man keinen Elementnamen an, erhält man ein sogenann-
tes unbenanntes Bitfeld, mit dessen Hilfe man die Ausrichtung der Bitfelder im
Speicher steuern kann. Ein unbenanntes Bitfeld der Größe 0 weist den Compi-
ler an, das nächste Element an den vom Compiler intern zur Speicherauftei-
lung verwendeten Bytegrenzen auszurichten (reduziert die Zugriffszeiten).

Beispiele
struct s_karten {
unsigned int wert : 3;
unsigned int farbe : 2;
unsigned int spieler : 2;
unsigned int gespielt : 1;
} karten[32];

int main() {
int farbe, wert, loop;
for(farbe=0; farbe<4; farbe++)
for(wert=0; wert<8; wert++) {
karten[8*farbe+wert].farbe = farbe;
karten[8*farbe+wert].wert = wert;
karten[8*farbe+wert].spieler = 0;
karten[8*farbe+wert].gespielt = 0;
}
for(loop=0; loop < 32; loop++)
printf("Farbe = %d, Wert = %d\n",karten[loop].farbe,
karten[loop].wert);
return 0;
}

Verweise
Siehe Strukturen

78
Unions

Unions
union typbezeichner {
Typ1 element1;
Typ2 element2;
};

Beschreibung
Eine Union ist ein Datentyp, der für verschiedene Elemente deklariert wird, dessen Variablen
aber nur eines der Elemente aufnehmen können. Die Größe einer Unionvariablen entspricht
der Größe des größten Elements.

Anwendung
Unions sparen gegenüber Strukturen Speicher, wenn nur ein Element benötigt wird,
dessen Typ aber vom Programmierer nicht vorhergesehen werden kann.

Warnung
Eine Union kann keine Variable ihres eigenen Typs als Element enthalten. Zeiger
oder Referenzen auf Variablen ihres eigenen Typs sind aber erlaubt.
Wird eine Unionvariable bei ihrer Definition initialisiert, kann nur dem ersten Uni-
onelement der Wert zugewiesen werden.
In C++ gibt es einige Besonderheiten zu beachten:
● In C++ sind Unions Klassen und dürfen auch Funktionen als Elemente enthal-
ten.
● Virtuelle Elementfunktionen sind nicht erlaubt.
● Unions können nicht Bestandteil von Klassenhierarchien sein.
● Klassen mit eigenen Definitionen für Konstruktor, Destruktor, Kopierkon-
struktor oder Zuweisungsoperator können nicht Element einer Union sein.

Syntax
union typbezeichner {
typ1 element1;
typ2 element2;
/* weitere Elemente */
};
● typbezeichner: Wird ein typbezeichner spezifiziert, kommt dies einer Typdefini-
tion gleich. Später können dann Variablen dieses Typs definiert werden. In C
lautet der Typ union typbezeichner, in C++ reicht einfach der typbezeichner.
● typ element: Innerhalb der Klammern werden die Elemente der Union dekla-
riert.

79
Sprachkonzepte und Syntax

Definition von Unionvariablen


union Login { /* Definition */ };
union Login user;
Oder
union Login{
char passwort[10];
int kennung;
} user1, user2;

Initialisierung
Bei der Initialisierung wie der Zuweisung kann man nur einem Element der Union
einen Wert zuweisen.
union Login user = {"Geheim"};

Zugriff auf Strukturelemente


[Link]
unionzeiger->strukturelement

Beispiele
#define KENNUNG

union Login{
char passwort[10];
int kennung;
};

int main()
{
union Login user1;

#ifdef KENNUNG
printf("Geben Sie ihre Kennummer ein: \n");
scanf("%d",&[Link]);
fflush(stdin);
#else
printf("Geben Sie ihr Passwort ein: \n");
scanf("%s",[Link]);
fflush(stdin);
#endif

printf("\n");
printf("Groesse der Union: %d\n",sizeof(Login));
return 0;
}

Verweise
Siehe Strukturen

80
Zeiger

Zeiger und Referenzen

Zeiger
typ* zeigervariable;

Beschreibung
Ein Zeiger ist eine Variable, in der sich die Adresse eines Datenobjektes oder einer Funktion
befindet. Die Verwendung von Zeigern bringt verschiedene Vorteile mit sich.

Anwendung
Einsatzgebiete für Zeiger
● Speicherersparnis. Zeigervariablen speichern Adressen. Ihr Speicherbedarf ist
also auf 16 oder 32 Bit festgelegt, wohingegen die Objekte, auf die sie zeigen,
wesentlich größer sein können.
● Übergabe an Funktionen. Durch die Übergabe von Zeigern (call by reference)
an Funktionen wird die Funktion in die Lage versetzt, auf Objekte zuzugrei-
fen, die außerhalb ihres Gültigkeitsbereiches liegen. Zudem ist die Übergabe
von Zeigern wesentlich schneller als das Kopieren großer Datenobjekte. (In
C++ werden aus den gleichen Gründen oft Referenzen übergeben.)
● Dynamische Speicherverwaltung. Mittels Zeigern kann der Programmierer
selbst entscheiden, wann Speicher reserviert und wann freigegeben wird. Zei-
ger erlauben die Implementierung dynamischer Datenstrukturen wie Listen
und Bäume.
● Rekursive Datenstrukturen. Zeiger können für Datentypen definiert werden,
die deklariert, aber noch nicht definiert sind. Auf diese Weise kann eine Klasse
beispielsweise Zeiger auf ihre eigenen Instanzen haben.
● Arrays von Zeigern auf Funktionen sind erlaubt, i.G. zu Arrays von Funktio-
nen.
● Generische Implementierungen. Mit Zeigern lassen sich viele Probleme effizi-
enter und/oder allgemeiner lösen. Beispielsweise durch Verwendung von Zei-
gern auf void, Zeigern auf Funktionen, um Funktionen als Argumente an
andere Funktionen zu übergeben, Basisklassenzeiger auf abgeleitete Objekte
zur Verwaltung von Objekten verschiedener abgeleiteter Klassen in einem Ar-
ray, Nutzung virtueller Methoden statt expliziter Laufzeitidentifizierung,

81
Sprachkonzepte und Syntax

Warnung
Ein Zeiger kann auf jedes beliebige Datenobjekt zeigen, mit zwei Ausnahmen:
● Referenzen und
● Bitfelder.

Syntax
typ* zeigervariable;
● typ: Datentyp der Objekte, auf die der Zeiger weist. Diese Angabe wird für die
korrekte Dereferenzierung des Zeigers benötigt.
● *: kennzeichnet die Variable als Zeiger und kann sowohl hinter der Typanga-
be stehen als auch vor dem Zeigernamen.
● zeigervariable: Name des Zeigers.

Initialisierung
Die Initialisierung eines Zeigers erfolgt durch die Zuweisung einer Adresse und
eines mit der Adresse verbundenen Speicherbereichs. Die Initialisierung kann auf
verschiedene Weisen geschehen.
1. Zuweisung der Adresse eines existierenden Objekts.
● Die Adresse einer Variablen kann über den Adreß-Operator & ermittelt wer-
den.
● Zeiger sind selbst Adressen.
● Die Namen von Arrays und Funktionen stellen ebenfalls Adressen dar.
int i_var = 13;
int *ptr1 = &i_var;
int *ptr2 = ptr1;
int feld[10] = {11,11,11};
ptr3 = feld;
2. Zuweisung von NULL.
● Zeiger, die auf kein Objekt gerichtet sind, sollten mit der NULL-Adresse in-
itialisiert werden. Auf diese Weise kann leicht getestet werden, ob der Zeiger
auf ein Objekt weist oder nicht.
double *ptr4 = NULL;

82
Zeiger

3. Allokation durch malloc() oder new.


● Die Funktion malloc() sowie der Operator new dienen dazu, Speicher zu reser-
vieren und die Adresse an den Zeiger zu übergeben. Auf diese Weise werden
Objekte eingerichtet, die nur über Zeiger erreichbar sind.
double *ptr5 = new double;
int *ptr6 = (int*) malloc(3*sizeof(int));
Nichtinitialisierte Zeiger enthalten undefinierte Bitmuster, die bei der Dereferenzie-
rung als Adresse interpretiert werden. Dies führt unweigerlich zu Programmfehlern
und oftmals zu Programmabstürzen.

Dereferenzierung
Zeiger sind Adressen. Dereferenzierung bedeutet, über diese Adresse auf das refe-
renzierte Objekt zuzugreifen. Dazu dienen die Dereferenzierungs-Operatoren *, -
>,.* und ->* .
● *: der eigentliche Dereferenzierungs-Operator.
● ->: eine Verbindung aus Dereferenzierungs- und Punkt-Operator, der einen
Zeiger auf einen Klassentyp dereferenziert und gleichzeitig auf ein Element des
referenzierten Objekts zugreift.
● .*: dereferenziert einen Zeiger auf ein Klassenelement für ein gegebenes Klas-
senobjekt.
● ->*: dereferenziert einen Zeiger auf ein Klassenelement für einen gegebenen
Zeiger auf ein Klassenobjekt.

Beispiel
#include <stdio.h>

int main() {
int i;
int *p_i = &i; // Deklaration und Initialisierung

struct koord {
int x,y;
} pos;
struct koord *p_pos1 = &pos; // Deklaration und Initialisierung

// Dereferenzierung
*p_i = 2;
(*p_pos1).x = 3; // Dereferenzierung einer Struktur mit *
p_pos1->y = p_pos1->x+1; // Dereferenzierung einer Struktur mit ->

printf("x = %d; y = %d\n",pos.x, pos.y);

return 0;
}

83
Sprachkonzepte und Syntax

liefert folgende Ausgabe:


x = 3; y = 4

Warnung
● Das Zeichen * wird also in der Deklaration dazu benutzt, eine Zeigervariable
zu spezifizieren. In Anweisungen teilt es dem Compiler mit, daß nicht die
Adresse, die in der Zeigervariablen gespeichert ist, gefragt ist, sondern das
Objekt, das an dieser Adresse abgelegt ist.
● Ein Zeigername ist eine Adresse. Diese Adresse verweist auf die Speicherzelle,
in der der Wert des Zeigers abgelegt wird. Der Wert eines Zeigers ist ebenfalls
eine Adresse. Diese Adresse wird benutzt, um auf andere Datenobjekte zu ver-
weisen.
● Dereferenzieren Sie niemals Zeiger, die ungültige Adressen beinhalten (nicht-
initialisierte Zeiger, Zeiger auf Objekte, die nicht mehr existieren, etc.).

Spezielle Zeiger
Zeiger auf Zeichenketten char*
Ein Zeiger vom Typ char* weist auf ein einzelnes Zeichen. Viele Bibliotheksfunktio-
nen, die Zeichenketten verarbeiten (strcpy(), strlen() etc.), erwarten als Argument
solch einen Zeiger auf das erste Zeichen einer zu verarbeitenden Zeichenkette. Die
so übergebene Zeichenkette beginnt mit der Adresse, die der Zeiger liefert, und
endet mit dem ersten Auftauchen des Nullzeichens '\0'.
Bei der Verwendung der entsprechenden Bibliotheksfunktionen ist daher darauf zu
achten, daß die übergebenen Zeiger auch stets auf nullterminierte Zeichenketten
verweisen, und daß Zeichenketten nur in Speicherbereiche kopiert oder geschrieben
werden, die groß genug sind, die gesamte Zeichenkette einschließlich Nullterminie-
rungszeichen aufzunehmen. Ansonsten kommt es zu unerwünschten Speicherzugrif-
fen – meist begleitet von Programmabstürzen.
char str[20] = "Hello World!";
// reserviere Speicher so groß wie der String in str plus '\0'
p_str = (char*) malloc(strlen(str)+1);
strcpy(p_str,str);

Zeiger auf void void*


Ein void* (Zeiger auf void) ist ein universeller, typenloser Zeiger. Er wird eingesetzt,
wenn der Typ des Zeigers nicht feststeht oder allgemein gehalten werden soll. Erst
in einer nachfolgenden expliziten Typumwandlung wird festgelegt, wie der zum
Zeiger gehörende Speicherplatz interpretiert werden soll, ob zum Beispiel als float-
Wert oder als String.

84
Spezielle Zeiger

// Vergleichsfunktion für Verwendung mit qsort()


// vergleicht zwei Adressen nach dem Namen
int vgl(const void* p1,const void* p2) {
struct adresse* adr1,*adr2;
adr1=(struct adresse*)p1;
adr2=(struct adresse*)p2;
return strcmp(adr1->name,adr2->name);
}

Zeiger auf Funktionen *func


Zeiger auf Funktionen werden dazu benötigt, Funktionen als Parameter an andere
Funktionen zu übergeben.
Rückgabetyp (*zeigername) (Parametertypen);
● Rückgabetyp: gibt den Rückgabetyp der Funktionen an, auf die der Zeiger ge-
richtet werden kann.
● zeigername: ist der Name des Zeigers.
● Parametertypen: Liste der Parametertypen der Funktionen, auf die der Zeiger
gerichtet werden kann.
void func(int i, class person leser) {...};
void (*func_ptr) (int, class person) = func;

Konstante Zeiger *const


Bei der Zeigerdeklaration unterscheidet man zwischen const-Zeigern, die nicht auf
andere Objekte umgelenkt werden können, und Zeiger auf const-Objekte. Letztere
werden häufig in Funktionsdefinitionen verwendet, um zu verhindern, daß in der
Funktion über den Zeigerparameter das Objekt, auf das der Zeiger weist, verändert
wird.
char c = 'A';
const char *ptr_c; // Zeiger auf const-Objekt
char const *ptr_c; // Zeiger auf const-Objekt
char *const ptr_c = &c; // const-Zeiger
int func (int par1, const char *par2);

Zeiger auf Datenelemente class::*


Mit Hilfe des Bereichsoperators :: kann ein Zeiger einer Klasse zugeordnet werden.
Zur Definition und Initialisierung des Zeigers wird dabei lediglich der Name der
Klasse verwendet. Erst beim Zugriff über den Zeiger werden Instanzen oder Zeiger
auf Instanzen benötigt.
// Definition:
int person::* int_ptr; // person sei eine Klasse

// Initialisierung:
int person::* int_ptr = &person::plz;

85
Sprachkonzepte und Syntax

// Zugriff:
class person leser, *p_leser;
leser.*int_ptr = 66111;
p_leser->*int_ptr = 66111;

Zeiger auf Methoden class::*func


Mit Hilfe des Bereichsoperators :: kann ein Zeiger einer Klasse zugeordnet werden.
Zur Definition und Initialisierung des Zeigers wird dabei lediglich der Name der
Klasse verwendet. Erst beim Zugriff über den Zeiger werden Instanzen oder Zeiger
auf Instanzen benötigt.
// Definition:
void (person::*func_ptr) (int); // person ist eine Klasse

// Initialisierung:
void (person::*func_ptr) (int) = &leser::print_adresse;

// Zugriff:
class person leser, *p_leser;
(leser.*func_ptr) (64);
(p_leser->*func_ptr) (64);

Zeiger auf statische Klassenelemente class::static*


Zeiger auf statische Klassenelemente werden wie Nicht-Element-Zeiger behandelt,
d. h., der Zeiger wird ohne eine Klassenangabe dereferenziert:
int *int_ptr = &Klassenname::Statisches_Datenelement;
int a = *int_ptr;

Basisklassenzeiger (basis*)
In C++ kann jedes abgeleitete Objekt auch als Objekt einer seiner eindeutigen Basis-
klassen angesehen werden. Entsprechend kann ein Zeiger auf ein abgeleitetes Objekt
ohne Probleme in einen Zeiger auf eines seiner eindeutigen Basisklassen umgewandelt
werden. Dies erlaubt beispielsweise, die Verwaltung abgeleiteter Objekte unter-
schiedlicher Klassen als Basisklassenobjekte in einem gemeinsamen Array.
Basisklassenzeiger werden zumeist in Zusammenhang mit virtuellen Methoden einge-
setzt.
class Basis {...}; // Klassenhierarchie
class Abg1 : public Basis {...};
class Abg2 : public Basis {...};

class Basis *feld[10]; // Array

feld[0] = new Abg1; // Zeiger in Array


feld[1] = new Abg2; // aufnehmen

86
Referenzen (nur C++)

this-Zeiger this
Jede nicht-statische Methode einer Klasse erhält vom Compiler intern einen zusätz-
lichen Parameter zugewiesen. Dies ist der this-Zeiger, der auf die Anfangsadresse
der jeweiligen Instanz verweist, für die die Methode aufgerufen wird.
#include <iostream>
using namespace std;

class demo
{
public:
void func() {cout << this;}
};

int main()
{
class demo d1,d2;
cout << "This-Zeiger der Instanz d1 = " << [Link]() << endl;
cout << "This-Zeiger der Instanz d2 = " << [Link]() << endl;
return 0;
}

Referenzen (nur C++)


typ& referenzname = var;

Beschreibung
Referenzen verweisen wie Zeiger auf Objekte, können jedoch nur einmal mit einem Objekt
initialisiert und danach nicht mehr auf andere Objekte umgelenkt werden. Zudem entfällt für
Referenzen die typische Zeigersyntax – sie werden wie ganz normale Variable, quasi als Syn-
onyme der Variablen, auf die sie verweisen, verwendet.
Technisch gesehen entspricht eine Referenz damit einem const-Zeiger, der bei jedem Zugriff
automatisch dereferenziert wird.

Anwendung
Referenzen, auch Aliase genannt, sind im Gebrauch den Zeigern verwandt und
werden in ähnlicher Weise zur Übergabe von Variablen an Funktionen eingesetzt,
wenn die Funktionen die übergebenen Variablen direkt ändern (call by reference)
oder Laufzeitverschlechterungen durch Kopieren großer Datenobjekte vermieden
werden sollen. Referenzen haben dabei aber den Vorteil,
● daß sie wie normale Variablen angesprochen werden (die zeigertypische Dere-
ferenzierungssyntax entfällt)
● daß ihr Einsatz sicherer ist als der von Zeigern (da sie immer auf ein genau de-
finiertes Objekt verweisen)

87
Sprachkonzepte und Syntax

Warnung
Eine Referenzvariable muß direkt bei ihrer Deklaration initialisiert werden, außer
● sie ist explizit als extern deklariert,
● es handelt sich um einen Funktionsparameter,
● es handelt sich um ein Klassenelement.
Eine Referenzvariable kann nur auf eine Variable gesetzt werden. Sie kann nicht
auf eine andere Variable umgesetzt werden!
Es lassen sich keine Zeiger auf Referenzen definieren.
Es lassen sich keine Arrays von Referenzen bilden.
Es gibt keine Referenzen auf Referenzen.
Referenzen können nicht vom Typ void& sein.

Syntax
typ& referenzname = var;
● typ: Datentyp des Objekts, auf das die Referenz verweist.
● &: Referenzoperator &, der in der Deklaration eine Variable als Referenz
kennzeichnet.
● referenzname: Name der deklarierten Referenzvariablen.
● = var: Referenzen müssen direkt bei der Definition initialisiert werden.

Beispiele
Das folgende Beispiel demonstriert die Übergabe von Argumenten an Referenzpara-
meter.
#include <iostream>
using namespace std;

class Leute {
int alter;
public:
Leute(int age) {alter = age;}
void altern() {alter++;}
int get_alter() {return alter;}
};

// Funktion mit Referenzparameter


void uebergebe_referenz(Leute& par)
{
[Link]();
}

int main()

88
Typdefinitionen

{
Leute dennis(30);
cout << "Dennis ist " << dennis.get_alter()
<< " Jahre alt\n";

// Übergabe des Klassenobjekts an Referenzparameter


uebergebe_referenz(dennis);
cout << "Dennis ist " << dennis.get_alter()
<< " Jahre alt\n";
return 0;
}
Ausgabe
Dennis ist 30 Jahre alt
Dennis ist 31 Jahre alt

Warnung
Bei der Parameterübergabe müssen Datentyp des Referenzparameters und Datentyp
des Arguments genau übereinstimmen. Ansonsten gilt:
● Für const-Referenzparameter nimmt der Compiler eine Typumwandlung vor
und erzeugt eine zu dem Referenzparamter passende temporäre Variable. Der
Referenzparameter weist dann auf diese temporäre Variable. Die Zurückliefe-
rung von Werten über den Parameter an das Aufrufargument ist daher nicht
mehr möglich, für const-Parameter aber auch sicherlich nicht vorgesehen.
● Für nicht-const-Referenzparameter gibt der Compiler eine Fehlermeldung aus.
(Einige ältere Compiler geben nur eine Warnung aus und legen eine temporäre
Variable an.)

Typdefinitonen und Typumwandlungen

Typdefinitionen
typedef

Beschreibung
C erlaubt die Definition beliebiger Datentypen auf der Grundlage der im Sprachumfang enthal-
tenen Typen. Bei einer Typdefinition wird ein neuer Typ spezifiziert und mit einem Bezeichner
für den Typ verbunden. Eine solche Typdefinition kann durch die Schlüsselworte struct, union,
class oder typedef erfolgen.

89
Sprachkonzepte und Syntax

Anwendung
Mit typedef werden im Grunde keine neuen Typen definiert, sondern lediglich Syn-
onyme für bereits mögliche Typspezifikationen eingerichtet. Dies kann aus zwei
Gründen geboten sein:
● Eine Typdefinition soll per Präprozessorschalter anpaßbar sein (erstes Bei-
spiel).
● Eine komplexe Typdefinition soll durch ein einfaches Synonym repräsentiert
werden (zweites Beispiel)

Warnung
typedef-Typen sind nicht erweiterbar:
typedef int INT;
unsigned INT x; // nicht erlaubt

Syntax
typedef typ_spezifikation typbezeichner;
● typ_spezifikation: Hier wird der neue Typ definiert. Die Form der Typangabe
entspricht der Angabe in Variablendeklarationen.
● typbezeichner: Name für den neuen Typ.

Beispiele
Typdefinitionen in Abhängigkeit von Compiler-Schaltern:
#if defined (LONG)
typedef wchar_t long;
#else
typedef wchar_t int;
#endif
Typdefinitionen als Vereinfachungen:
typedef unsigned int UINT; // Beispiel aus windows.h
typedef void (*func_typ) (int, int); // definiert func_typ

Standardkonvertierungen
Beschreibung
In verschiedenen Situationen nimmt der Compiler automatische Typkonvertierungen vor.

Anwendung
Die wichtigsten automatischen Konvertierungen sind:

90
Standardkonvertierungen

Bezeichner
● Auf der rechten Seite von Zuweisungen werden Bezeichner als R-Werte (Wert,
nicht Speicheradresse) aufgefaßt.
● Array-Namen werden auf der rechten Seite von Anweisungen (inklusive Funk-
tionsaufrufen) als Zeiger auf ihr erstes Element aufgefaßt.
● Funktionsnamen repräsentieren auf der rechten Seite von Anweisungen den
Rückgabewert der Funktion.

Typangleichung
● Arithmetische Datentypen können ineinander konvertiert werden, wenn der
Datentyp, in den konvertiert wird, geeignet ist, den zu konvertierenden Wert
aufzunehmen (bei Konvertierung von Gleitkommazahlen in Integer-Werte geht
dabei der Nachkommaanteil verloren).
● Für binäre Operatoren, die arithmetische Operanden übernehmen, gleicht der
Compiler automatisch die Typen beider Operanden an – man bezeichnet dies
als die standardmäßige arithmetische Konvertierung.

Boolesche Wahrheitswerte
● Null-Zeiger und Null-Repräsentationen arithmetischer Datentypen können in
den Booleschen Wert false konvertiert werden, andere Werte dieser Daten-
typen werden entsprechend als true interpretiert.
● Umgekehrt kann der Boolesche Wert false in eine arithmetische Null, true in
eine Eins konvertiert werden.

Zeiger und Klassen


● Arraynamen werden auf der rechten Seite von Anweisungen (inklusive Funkti-
onsaufrufen) als Zeiger auf ihr erstes Element aufgefaßt.
● Funktionsnamen können als Zeiger auf sich selbst aufgefaßt werden.
● Zeiger auf spezielle Datentypen können in Zeiger auf void verwandelt werden
(der umgekehrte Weg ist nur durch explizite Typumwandlung erreichbar).
● Ein Zeiger auf eine abgeleitete Klasse kann in einen Zeiger auf eine eindeutige,
zugängliche Basisklasse konvertiert werden.
● Unter den gleichen Voraussetzungen kann die Instanz einer abgeleiteten Klasse
als Instanz einer Basisklasse interpretiert werden.
● Zeiger auf Elemente einer Basisklasse können in Zeiger auf Elemente einer ein-
deutigen, zugänglichen abgeleiteten Klasse konvertiert werden.

91
Sprachkonzepte und Syntax

● Wenn Sie einer Klasseninstanz einen Wert zuweisen und in der Klasse ein ent-
sprechender Konstruktor definiert ist, der mit genau einem Argument des
Typs aufgerufen wird, dem auch der Wert angehört, wird der Konstruktor wo
nötig zur automatischen Konvertierung von Werten des entsprechenden Da-
tentyps in Objekte der Klasse herangezogen (kann durch explicit-Deklaration
unterbunden werden).

const und volatile


● Die Qualifizierer const und volatile können automatisch beigefügt, aber nicht
abgezogen werden (so kann ein nicht-const Argument an einen const-Parame-
ter übergeben werden, aber nicht umgekehrt).

Beispiele
Operandenkonvertierung
float f = 3/4; // ergibt 0.0;
// Integer-Division von 3/4 ergibt 0
// 0 wird für Zuweisung in 0.0 umgewandelt
float f = 3/4.0; // ergibt 0.75;
// 4.0 ist Gleitkommazahl, der Integer-Operand 3
// wird daher in Gleitkommazahl umgewandelt
// Es wird eine Gleitkomma-Division durchgefuehrt
Konstruktoren mit einem Argument
class Feld {
public:
int anzahl;
Feld(int a) {anzahl = a;}
};
...
Feld stack(3);
stack = 13; // impliziter Aufruf: stack = Feld(13);

Typumwandlung
(typ) wert

Beschreibung
Gelegentlich ist es wünschenswert, daß eine Variable eines bestimmten Datentyps als einem
anderen Datentyp angehörig behandelt wird. Sofern eine solche Typumwandlung durchführbar
ist, kann sie durch den C-Cast-Operator () oder die C++-Operatoren const_cast, dynamic_cast,
static_cast und reinterpret_cast, die als Schlüsselworte in die Sprache aufgenommen sind,
explizit herbeigeführt werden.

92
Typumwandlung

Anwendung
Für Typkonvertierungen gibt es fünf typische Gründe:
● Sie wollen eine Gleitkommazahl in eine Integer-Zahl verwandeln oder umge-
kehrt. Letzeres ist beispielsweise geboten, wenn Sie eine Integer-Zahl durch
eine andere Integer-Zahl teilen wollen, das Ergebnis aber mit Divisionrest in
einer Gleitkommavariablen gespeichert werden soll.
● Sie haben einen void-Zeiger vorliegen, den Sie in einen Zeiger auf einen be-
stimmten Datentyp umwandeln wollen.
● Sie haben einen Basisklassenzeiger auf ein abgeleitetes Objekt, den Sie in einen
Zeiger auf die abgeleitete Klasse umwandeln wollen.
● Sie wollen durch die Typumwandlung eines Zeigers eine bestimmte Speicher-
interpretation erzwingen. Diese Möglichkeit ist selten erforderlich, dafür aber
recht fehleranfällig.

Der Cast-Operator von C


Der Cast-Operator kann benutzt werden, um in einer Anweisung den Typ des Aus-
drucks der rechten Seite in den Typ des Bezeichners der linken Seite umzuwandeln:
bezeichner1 = (Typ_von_bezeichner1) AUSDRUCK;
bezeichner1 = (Typ_von_bezeichner1) bezeichner2;
Eine zweite Form der Syntax wandelt den Typ einer Variablen direkt um
bezeichner = Datentyp();

Die Cast-Operatoren von C++


Die C++-Operatoren sind vor allem dazu gedacht, die verschiedenen Konvertierun-
gen nach ihrem Gefahrenpotential zu kategorisieren, und die Textsuche nach den
Konvertierungen zu erleichtern.

Operator Einsatzgebiet
static_cast<Typ>(var) Zur Umwandlung zwischen »nahe verwandten« Typen
– also alle Fälle, in denen der Compiler auch eine impli-
zite Konvertierung vornehmen könnte, plus einige
einfache Sonderfälle.
reinterpret_cast<Typ>(var) Für fast alle anderen erlaubten Umwandlungen.
const_cast<Typ>(var) Entfernt eine const- oder volatile-Deklaration aus
einem Typ.
dynamic_cast<Typ>(var) Zur Umwandlung zwischen Zeigern oder Referenzen
auf Klassentypen einer gemeinsamen Klassenhierarchie

93
Sprachkonzepte und Syntax

Beispiele
int i = int(3.14);
double var = (double) 13/2);
int ptr = (int *) malloc(80 * sizeof(int));

Abgeleitet *p_abg = new Abgeleitet;


Basis *p_bp = p_abg;

p_abg = dynamic_cast <Abgeleitet*> (p_bp);

Konstanten

Konstanten
Beschreibung
Neben den Variablen stellen die Konstanten die zweite Möglichkeit zur Repräsentation von
Daten in Programmen dar. Der Unterschied zwischen Variablen und Konstanten liegt auf der
Hand: Während eine Variable im Laufe eines Programms unterschiedliche Werte annehmen
und repräsentieren kann, stellt eine Konstante immer einen festen Wert dar.
C/C++ kennt 3 verschiedene Typen von Konstanten:
– Literale
– Symbolische Konstanten
– Konstante Variablen

Anwendung
Konstanten stellen eine Möglichkeit dar, feststehende Daten direkt im Programm-
code zu verankern: etwa um den Zahlenwert von PI in eine Formel einzubauen
oder in Form einer String-Tabelle für Fehlermeldungen des Programms.

Literale
Beschreibung
Die einfachste Form der Konstante ist ein konstanter Wert. Um sie von den konstanten Varia-
blen zu unterscheiden, bezeichnet man die konstanten Werte auch als Literale.

94
Literale

Anwendung
Konstante Werte werden bei der Übersetzung durch den Compiler hartcodiert,
d. h., die Werte sind nicht irgendwo im Speicher abgelegt, von wo sie bei Bedarf
ausgelesen werden können, sondern die Werte stehen direkt in den betreffenden
Maschinenbefehlen.
Die einzige Ausnahme: für String-Literale wird Speicher reserviert, doch hat der
Programmierer üblicherweise keinen Zugriff auf diesen Speicherbereich.
printf("Hello World\n");
Die automatische Speicherallokation erlaubt allerdings die Zuweisung von String-
Literalen an Zeiger auf char.
char *str1;
str1 = "Hello World\n";

Datentyp Literal
bool true, false
char 'c', 'Ü', '\n', '\\',
'ab' (Multibyte-Zeichen)
wchar_t L'c', L'Ü', L'\n', L'\\',
L'ab' (Multibyte-Zeichen)
Zeichenketten (char*) "Dies ist ein String"
Zeichenketten (wchar_t*) L"Dies ist ein String"
short 12, -128
int 12, -128, 128u, 1277U
012, -077 (Oktal)
0x12, 0XEE (Hexadezimal)
long 12l, 1400000L, 12lu
float 47.11f, 12.0F, 10e-2F
double 47.11, 12.0, 10e-2
long double 47.11l, 12.0L, 10e-2L

Warnung
Wichtig bei der Verwendung von Literalen ist, daß Sie sich an die vorgesehene Syn-
tax zur Angabe der Werte halten, damit der Compiler aus dem Wert auch den
zugehörigen Datentyp ablesen kann.

95
Sprachkonzepte und Syntax

Beispiele
int i = 513; // Zuweisung einer Konstanten an eine Variable
double feld[30]; // Angabe der Array-Groesse
if( (x < 100) && (x > 50)) // Zur Formulierung von
if(!strcmp(str,"Vergleichstext"); // Bedingungen

Verweise
Siehe #define
Siehe const-Variablen

#define – symbolische Konstanten


Beschreibung
Symbolische Konstanten sind Bezeichner, die als Aliase für einen bestimmten Wert definiert
sind.

Anwendung
Wird eine Konstante mehrfach verwendet, ist es sinnvoll, sie vorab zu deklarieren
und mit einem symbolischen Namen zu verbinden, der dann im weiteren Verlauf
des Programms die Konstante repräsentiert. Dies ermöglicht die Präprozessor-
Direktive #define:
#define symbolBezeichner KONSTANTE
Danach kann der symbolische Bezeichner im weiteren Quelltext stellvertretend für
die Konstante eingesetzt werden. Bei der Kompilation werden alle Vorkommen des
symbolischen Bezeichners durch die zugehörige Konstante ersetzt.
Der Vorteil besteht einmal darin,
● daß Sie eine Konstante mit einem aussagekräftigen Namen verbinden können,
und
● zum anderen nur die #define-Anweisung anpassen müssen, wenn Sie die Kon-
stante mit einem anderen Wert verbinden wollen (beispielsweise ist es sinn-
voll, Obergrenzen für Arrays, Abbruchbedingungen für Schleifen oder Schalter
für die bedingte Kompilation mit Hilfe von #define am Dateianfang festzule-
gen, damit man sie später bei Bedarf schnell findet und zentral ersetzen kann).

Vordefinierte Konstanten
Eine Reihe interessanter Konstanten sind bereits in den Header-Dateien der Stan-
dardbibliothek vordefiniert, so zum Beispiel

96
#define – symbolische Konstanten

Header-Datei Konstante Wert


stddef.h NULL Makro, das zu implementierungsspezifischer Nullzei-
gerkonstante expandiert wird, beispielsweise 0 oder 0L.
stdio.h EOF Üblicherweise -1 bzw (wint_t)(0xFFFF) für wchar_t
FOPEN_MAX Makro, das zu Integer-Wert expandiert wird, der die
Mindestanzahl der Dateien anzeigt, die gleichzeitig ge-
öffnet werden können.
limits.h CHAR_BIT 8 (Anzahl Bits in Typ char)
INT_MIN -2147483647L-1 (für 32-Bit-System)
INT_MAX 2147483647L (für 32-Bit-System)
FLT_RADIX 2 (Basis der Exponentdarstellung)
FLT_DIG 6 (Anzahl der Dezimalstellen)

Beispiele
#define STUNDE 60
#define dutzend 12
#define Name "C++Compiler"
Der symbolische Bezeichner ist lediglich ein Aliasname für ein Literal. Vor der
eigentlichen Übersetzung in Objektcode geht der Compiler (genauer gesagt der Prä-
prozessor) den Quelltext durch und ersetzt alle Vorkommen des symbolischen
Bezeichners durch die zugehörige Konstante. Wenn es dann an die eigentliche Über-
setzung geht, sieht der Quelltext so aus, daß es keine symbolischen Konstanten,
sondern nur noch Literale gibt:
Original-Quelltext
#define MAX 30
double feld[MAX];
...
for (int i = 0; i < MAX; i++) {...}
...
for (int i = 0; i < MAX; i++) {...}
...
if (i < MAX) {...}
Nach Bearbeitung durch Präprozessor:
double feld[30];
...
for (int i = 0; i < 30; i++) {...}
...
for (int i = 0; i < 30; i++) {...}
...
if (i < 30) {...}

Verweise
Siehe Zusammengesetzte Datentypen, Aufzählungstypen

97
Sprachkonzepte und Syntax

const – konstante Variablen


Beschreibung
Die letzte Form der Konstanten ist die konstante Variable – eine Variable, deren Wert nach der
Initialisierung nicht mehr verändert werden kann.

Anwendung
Konstante Variablen werden mit den Schlüsselwort const deklariert. Sie sind aus
Sicht des Compilers keine echten Konstanten, sondern vielmehr Variablen, die er
vorm Überschreiben schützt.
In C wie C++ kann man mit const
● beliebige Objekte (also auch Variablen selbst definierter Datentypen wie
Strukturen und Klassen) als konstant deklarieren,
● verhindern, daß als Zeiger übergebene Funktionsargumente in einer Funktion
verändert werden,
● Zuweisungsmöglichkeiten erweitern,
● stärker von der Typprüfung des Compilers profitieren.

Warnung
In C++ wird eine konstante Variable wie eine echte Konstante angesehen.
In C, das nach ANSI ebenfalls das Schlüsselwort const kennt, können konstante
Variablen jedoch nicht an Stellen verwendet werden, an denen der Compiler eine
Konstante bzw. einen konstanten Ausdruck erwartet – also
● nicht bei der Angabe der Größe eines Arrays,
● nicht als case-Marken.

Beispiele
const int monate = 12;
int func (const int par1, const char *par2);

Verweise
Siehe Literale
Siehe #define
Siehe Klassen, Konstante Datenelemente und Methoden

98
Operatoren

Operatoren

Operatoren
Beschreibung
ANSI C/C++ kennt mehr als 40 Operatoren. Mit diesem Wert übersteigt bei C/C++, und das ist
bei Programmiersprachen nicht üblich, die Anzahl der Operatoren die Anzahl der Schlüsselwör-
ter der Sprache. Der größte Teil der Operatoren stammt bereits aus der Zeit der ersten Sprach-
definition durch Kernighan & Ritchie.
Bei den hier aufgelisteten Formen der Operatoren handelt es sich um ihre ursprüng-
lichen Definitionen und nicht um überladene Versionen. Die meisten der Operato-
ren können von Programmen überladen werden (nicht jedoch für die elementaren
Datentypen, für die sie bereits standardmäßig definiert sind) und nur unter Beibe-
haltung ihrer üblichen Syntax.

Operator Kurzbeschreibung
+ addiert zwei Operanden
+= addiert zwei Operanden und weist Ergebnis zu
- subtrahiert zwei Operanden
-= subtrahiert zwei Operanden und weist Ergebnis zu
* multipliziert zwei arithmetische Operanden
*= multipliziert zwei arithmetische Operanden und weist Ergebnis zu
/ dividiert zwei arithmetische Operanden
/= dividiert zwei arithmetische Operanden und weist Ergebnis zu
% Modulo-Operator, ermittelt den Rest einer Ganzzahldivision
%= Modulo-Operator mit gleichzeitiger Zuweisung
! Nicht-Operator, Verneinung
not Nicht-Operator, Verneinung
!= vergleicht zwei arithmetische Operanden auf Ungleichheit
not_eq vergleicht zwei arithmetische Operanden auf Ungleichheit
& Bei einem Operanden liefert dieser Operator die Adresse des Operanden
& Bei zwei Operanden wird eine bitweise UND-Verknüpfung ausgeführt
bitand Bitweise UND-Verknüpfung
&= Bitweise UND-Verknüpfung und Zuweisung
and_eq Bitweise UND-Verknüpfung und Zuweisung
&& Logische UND-Verknüpfung

99
Sprachkonzepte und Syntax

Operator Kurzbeschreibung
and Logische UND-Verknüpfung
() Cast-Operator, erzwingt Typumwandlung
, Operator für sequentielle Auswertung, Kommaoperator
++ inkrementiert den Operanden
-- dekrementiert den Operanden
-> Elementverweis-Operator
. Punkt-Operator
* Indirektions-Operator
= Zuweisungsoperator
== testet auf Gleichheit
< Kleiner als
> Größer als
<= Kleiner als oder gleich
=> Größer als oder gleich
<< Bitweise Linksverschiebung
<<= Bitweise Linksverschiebung und Zuweisung des Ergebnisses
>> Bitweise Rechtsverschiebung
>>= Bitweise Rechtsverschiebung und Zuweisung des Ergebnisses
?: Bedingungsoperator
[] Array-Indizierung
^ Bitweises exklusives ODER
xor Bitweises exklusives ODER
^= Bitweises exklusives ODER und Zuweisung des Ergebnisses
xor_eq Bitweises exklusives ODER und Zuweisung des Ergebnisses
| Bitweises ODER
bitor Bitweises ODER
|= Bitweises ODER und Zuweisung des Ergebnisses
or_eq Bitweises ODER und Zuweisung des Ergebnisses
|| Logisches ODER
or Logisches ODER
~ Komplement
compl Komplement
: Klasseninitialisierer
:: Bereichsoperator
.* Dereferenzierung von Zeigern auf Klassenelemente
->* Dereferenzierung von Zeigern auf Klassenelemente

100
Vorzeichen

Operator Kurzbeschreibung
sizeof ermittelt Größe des Operanden in Bytes
new Dynamische Speicherreservierung
new[] Dynamische Speicherresevierung für Arrays
delete Speicherfreigabe
delete[] Speicherfreigabe für Arrays
# Zeichenkettenbildung
## Grundsymbolverbindung
defined testet, ob Makro definiert ist
typeid Dynamische Typinformation

Klassifizierung
Alle Operatoren lassen sich, je nachdem, mit wie vielen Operanden sie arbeiten,
einer der folgenden Gruppen zuordnen:
● unäre Operatoren (arbeiten mit einem Operanden),
● binäre Operatoren (arbeiten mit zwei Operanden) und
● ternäre Operatoren (arbeiten mit drei Operanden).

Vorzeichen
Beschreibung
Unärer Operator der festlegt, ob ein Zahlenwert positiv oder negativ ist.

Anwendung
Mit den unären Operatoren »+« und »-« können Sie arithmetischen Typen ein Vor-
zeichen zuweisen. Werte ohne Vorzeichen sind automatisch positiv.

Operator Bedeutung
+ positiver Wert
- negativer Wert

Beispiele
int var1, var2;
var1 = -3;
var2 = 3 * -var1;

101
Sprachkonzepte und Syntax

Arithmetische Operatoren
Beschreibung
Binäre Operatoren zur Durchführung der algebraischen Verknüpfungen: Addition, Subtraktion,
etc., sowie der Divisionsrestberechnung.

Anwendung
Mit den arithmetischen Operatoren können Sie, wie es der Name vermuten läßt,
einfache arithmetische Operationen durchführen, wie sie auch in anderen Program-
miersprachen üblich sind.

Operator Bedeutung
+ Addition
- Subtraktion
* Multiplikation
/ Division
% Modulo, Rest einer Ganzzahldivision

Warnung
● Werden in einem Ausdruck mehrere Operatoren verwendet, gilt: Punktrech-
nung geht vor Strichrechnung. Vorzeichen, Inkrement und Dekrement kom-
men vor Punktrechnung. Bei gleicher Priorität werden die Operatoren von
links nach rechts abgearbeitet.
● Generell gilt, daß jeder Operator einer Prioritätstufe zugeordnet ist, und Ope-
ratoren höherer Priorität vor Operatoren niedrigerer Priorität ausgewertet
werden.
● Durch Setzen von Klammern können Sie die Reihenfolge der Auswertung von
Operatoren selbst festlegen.

Beispiele
var1 = 5+3;
var2 = 20 % var1; // = 4
var2 = 3 * 4 + var1; // = 20
var2 = 3 * (4 + var1); // = 36

Verweise
Siehe Priorität und Assoziativität

102
In- und Dekrementoperator

In- und Dekrementoperator


Beschreibung
Inkrement und Dekrement bezeichnet die Erhöhung beziehungsweise Erniedrigung eines Wer-
tes um 1 Einheit.

Anwendung
Die Programmiersprache C/C++ stellt zwei Operatoren zur Verfügung, mit denen
der Wert einer Variablen inkrementiert (um eins erhöht) oder dekrementiert (um
eins vermindert) werden kann, wobei die Operatoren vor oder nach der Variablen
stehen können.
lwert++
++lwert
lwert--
--lwert
Die Position des Operators legt fest, wann die Erhöhung oder Erniedrigung der
Variablen berechnet wird. Wichtig ist dies, wenn der Operator in komplexeren
Ausdrücken verwendet wird.
int var1, var2 = 12, var3 = 12;
var1 = 3 * ++var2; // ergibt var1 = 39
var1 = 3 * var3++; // ergibt var1 = 36
Die Notation, bei der der Operator vor der Variablen steht, wird Präfix-Schreib-
weise genannt und führt dazu, daß der Wert der Variablen zuerst neu berechnet
wird, bevor er benutzt wird. In der Postfix-Schreibweise (der Operator steht nach
der Variablen) wird der Wert des Operanden benutzt, bevor er verändert wird.

Operator Bedeutung
++ Inkrementoperator, erhöht seinen Operanden um 1
-- Dekrementoperator, vermindert seinen Operanden um 1

Warnung
● Die In- und Dekrementoperatoren sind nicht für Aufzählungstypen definiert.
● Die In- und Dekrementoperatoren können auch bei Zeigern benutzt werden.
In diesem Fall wird die Adresse um die Größe des Objekts, auf das der Zeiger
zeigt, erhöht oder vermindert.
● Das Inkrement einer Variablen vom Typ bool ergibt 1, das Dekrement ist nicht
definiert.

103
Sprachkonzepte und Syntax

Beispiel
#include <stdio.h>

int main() {
int x,y;
x = 5;
y = 5;
printf("Wert von ++x ist %d\n", ++x);
printf("Wert von y++ ist %d\n", y++);
printf("x nach der Inkrementierung: %d\n", x);
printf("y nach der Inkrementierung: %d\n", y);
return 0;
}
Das Programm erzeugt folgende Ausgabe:
Wert von ++x ist 6
Wert von y++ ist 5
x nach der Inkrementierung: 6
y nach der Inkrementierung: 6

Zuweisungen
Beschreibung
Mit Zuweisungsoperatoren können Werte zugewiesen und verändert werden. Neben dem ein-
fachen Zuweisungsoperator gibt es auch die sogenannten zusammengesetzten Zuweisungs-
operatoren, mit denen in einer Anweisung sowohl eine Berechnung als auch eine Zuweisung
durchgeführt werden kann.

Anwendung
Grundsätzlich gilt, daß mit einer Zuweisung dem linken Operanden der Wert des
rechten Operanden zugewiesen wird. Damit dies möglich ist, muß der linke Ope-
rand veränderbar sein, sich also auf eine Adresse im Speicher beziehen. Diese Aus-
drücke werden als »L-Wert« bezeichnet.

Einfache Zuweisung =
Bei der einfachen Zuweisung erhält der linke Operand den Wert des rechten Ope-
randen.
int main() {
int bestand, eingang;
bestand = 10;
eingang = 20;
bestand = bestand + eingang;
return 0;
}

104
Zuweisungen

Zusammengesetzte Zuweisungen <x>=


Neben dem einfachen Zuweisungsoperator »=« gibt es die zusammengesetzten
Zuweisungsoperatoren, mit denen durch einen Operator gleichzeitig eine Berech-
nung und eine Zuweisung durchgeführt werden kann.
Die zusammengesetzten Zuweisungsoperatoren haben das Format:
<x>=
wobei <x> durch die Operatoren +, –, *, /, %, <<, >>, &, ^ oder | ersetzt werden
kann.
int main() {
int bestand, eingang;
bestand = 10;
eingang = 20;
bestand += eingang;
return 0;
}

Zuweisung an Klasseninstanzen operator =


Zuweisungen an Klasseninstanzen erfolgen durch Aufruf des überladenen Opera-
tors =. Wird der Operator nicht in der Klasse überladen, wird der Standardopera-
tor aufgerufen, der elementweise kopiert.
Neben der Zuweisung einer Klasseninstanz an eine Instanz der gleichen Klasse,
erlaubt der Standard-Zuweisungsoperator die Zuweisung eines Objekts einer ein-
deutigen als public abgeleiteten Klasse an ein Objekt ihrer Basisklasse, aber nicht
die Zuordnung eines Objekts einer Basisklasse an ein Objekt ihrer abgeleiteten
Klasse.
Durch Kopierkonstruktoren werden Zuweisungen bei der Initialisierung vorgenom-
men.
class Basis {
...
};
class Abgeleitet : public Basis {
...
};

int main() {
Abgeleitet abg;
Basis bs;

//abg = bs; // Fehler


bs = abg;

105
Sprachkonzepte und Syntax

Vergleichende Operatoren
Beschreibung
Mit den vergleichenden Operatoren, die auch relationale Operatoren genannt werden, wird ein
Vergleich zwischen zwei Operanden, die auch Ausdrücke sein können, durchgeführt. Das Ergeb-
nis dieser Operation ist entweder wahr oder falsch.

Anwendung
Ausdrücke, die vergleichende Operatoren enthalten, werden häufig als Kontrollbe-
dingung in do-, while- oder for-Schleifen und if-Anweisungen eingesetzt.

Operator Bedeutung
== Gleich
!= Ungleich
< Kleiner als
> Größer als
<= Kleiner als oder gleich
>= Größer als oder gleich

Warnung
● Das Ergebnis eines Vergleichs ist ein Wahrheitswert (true, false).
● Jeder Wert, der ungleich 0 ist, wird von C/C++ als true interpretiert.
● Zwei Zeiger gleichen Typs, die auf das gleiche Objekt weisen, sind gleich.
● Zeiger auf verschiedene Elemente einer Klasse sind ungleich, wobei spätere
Deklarationen höhere Adressen haben. Dies gilt allerdings nur, wenn kein Zu-
griffsspezifizierer zwischen den Deklarationen steht. Sollte dies der Fall sein,
ist das Ergebnis undefiniert.

Beispiele
if (var1 <= var2)
funktion();
do {
ergebnis = funktion();
} while (ergebnis != 0);

Logische Operatoren
Beschreibung
Die logischen Operatoren dienen der Verknüpfung oder Negierung logischer Aussagen.

106
Logische Operatoren

Anwendung
Die Programmiersprache C kennt drei logische Operatoren: UND, ODER und
NICHT. Beim logischen UND- und ODER-Operator wird der Wahrheitswert der
Operanden verknüpft, der logische NICHT-Operator konvertiert den logischen
Wert seines Operanden in dessen Gegenteil. Die Operanden müssen als Boolesche
Werte (true, false) interpretierbar sein.

Operator Bedeutung
&& Logisches UND
|| Logisches ODER
! Logisches NICHT

logisches UND &&


Mit dem Operator »&&« wird eine logische UND-Verknüpfung seiner Operanden
durchgeführt. Das Ergebnis der Verknüpfung hat nur dann den Wert true (ungleich
Null), wenn beide Operanden den Wert true (ungleich Null) besitzen.
Die Operanden werden von links nach rechts ausgewertet. Wenn der erste Operand
den Wert false (also Null) ergibt, wird der zweite Operand nicht ausgewertet. Die
folgende Wahrheitstabelle zeigt Ihnen die möglichen Kombinationen:

1. Operand 2. Operand Ergebnis


wahr wahr wahr
wahr falsch falsch
falsch wahr falsch
falsch falsch falsch

logisches ODER ||
Der logische ODER-Operator verknüpft seine Operanden, so daß das Ergebnis der
Verknüpfung den Wert true hat, wenn einer oder beide Operanden den Wert true
hat.
Die Operanden werden von links nach rechts ausgewertet. Wenn der erste Operand
den Wert true (also ungleich Null) ergibt, wird der zweite Operand nicht ausgewer-
tet. Die folgende Wahrheitstabelle zeigt Ihnen die möglichen Kombinationen:

1. Operand 2. Operand Ergebnis


wahr wahr wahr
wahr falsch wahr
falsch wahr wahr
falsch falsch Falsch

107
Sprachkonzepte und Syntax

Beispiele
Das Beispielprogramm gibt eine formatierte ASCII-Tabelle auf den Bildschirm aus.
In Zeile 7 wird der logische UND-Operator eingesetzt, um zu erreichen, daß die
Ausgabe nur dann erfolgt, wenn spalte einen Wert kleiner als 13 hat (pro Zeile sol-
len dreizehn Zeichen ausgegeben werden) und der Wert von zeichen kleiner ist als
256 (um auch nur die ASCII-Zeichen auszugeben).
In Zeile 8 wird der logische ODER-Operator eingesetzt, um zu erreichen, daß auch
die Zeichen des erweiterten IBM-Zeichensatzes ausgegeben werden, da isprint()
nur für die ASCII-Zeichen mit den Codes 32 bis 126 das Resultat true liefert.
#include <ctype.h>

int main() {
int zeile, spalte, zeichen;
printf("ASCII-Tabelle\n");
for(zeile = 0, zeichen = 0; zeile < 20; zeile++)
{
for(spalte=0; spalte<13 && zeichen<256; spalte++)
{
if (isprint(zeichen) || zeichen>127)
printf("%3c %3d
else
printf(" %3d
zeichen++;
}
printf("\n");
}
return 0;
}

logisches NICHT !
Der logische NICHT-Operator verkehrt den Wahrheitswert seines logischen Ope-
randen in dessen Gegenteil. Dabei wird der Wert 0 (false) in den Wert 1 (true)
umgewandelt und alle Werte ungleich 1 zu 0.

Beispiele
Das folgende Programm enthält eine Endlosschleife, in der der Anwender aufgefor-
dert wird, eine Zahl einzugeben. In der Schleife wird mit einer if-Abfrage über-
prüft, ob die Zahl 0 eingegeben wurde. Wenn ja, wird die Schleife mit break been-
det.
#include <stdio.h
int main() {
int zahl:
for (;;) {
printf("Geben Sie eine Zahl ein: ");

108
Datenzugriff

scanf("%d", &zahl);
if (!zahl)
break;
}
return 0;
}

Verweise
Siehe Kategorie Programmsteuerung, if-Bedingung
Siehe Kategorie Programmsteuerung, Schleifen

Datenzugriff
Beschreibung
Mehrere Operatoren von C und C++ dienen dem Zugriff auf Daten.

Anwendung
Diese Operatoren benötigt man, um auf einzelne Elemente eines Arrays, einer
Struktur, Union oder Klasse zuzugreifen. Auch der Gültigkeitsbereichoperator und
die Operatoren zur Dereferenzierung von Zeigern, die den Zugriff auf die Objekte
ermöglichen, auf die die Zeiger verweisen, gehören in diese Kategorie.

Operator Bedeutung
* Indirektions-Operator
[] Array-Indizierung
. Punkt-Operator
-> Elementverweis-Operator
.* Dereferenzierung von Zeigern auf Klassenelemente
->* Dereferenzierung von Zeigern auf Klassenelemente
:: Gültigkeitsbereichoperator

Dereferenzierungs-Operator *
Der Dereferenzierungs-Operator »*« dient dazu, einen Zeiger zu dereferenzieren
und auf dessen Objekt zuzugreifen.
Der Typ des Zeigers bestimmt den Typ des Ergebnisses. Wenn also der Operand
ein Zeiger auf int ist, hat das Ergebnis den Datentyp int.
int func(int *zeiger) {
int ergebnis;
*zeiger = ergebnis; /* Wert zuweisen */
}

109
Sprachkonzepte und Syntax

Warnung
● Der Dereferenzierungs-Operator kann nicht auf einen unvollständigen Typ,
beispielsweise einen Zeiger auf void, angewendet werden.
● Das Zeichen »*« wird ebenfalls bei der Deklaration von Variablen benutzt,
um anzugeben, daß die deklarierte Variable ein Zeiger ist. Es handelt sich
dann dabei nicht um einen Dereferenzierungs-Operator. Die Bedeutung ergibt
sich somit immer aus dem Kontext.

Array-Indizierung []
Der Operator »[ ]« kann verwendet werden, um gezielt auf einzelne Elemente eines
Arrays oder eines dynamisch reservierten Feldes zuzugreifen.
#define FELD_GROESSE 20
int array[FELD_GROESSE];
int dyn_feld = (int*) malloc(FELD_GROESSE*sizeof(int));
for (i=0; i < Feld_GROESSE; i++) {
array[i] = i;
dyn_feld[i] = i;
};

Warnung
● Das erste Element eines Arrays (Feldes) besitzt den Index 0.
● Intern wird der Indizierungsoperator vom Compiler durch eine Zeigerberech-
nung aufgelöst. Die Syntax array[i] ist daher identisch zu *(array+i).

Punkt-Operator .
Der Punkt-Operator dient dazu, auf einzelne Elemente einer Klasse, Struktur oder
einer Union zuzugreifen.
[Link]
● objekt: muß der Name einer Klasse, Struktur oder einer Union sein.
● element: muß der Name eines Elements sein.
struct person {
char name[20];
int plz;
};
int main() {
struct person leser;
strcpy([Link], "Otto");
[Link] = 5100;
return 0;
}

110
Datenzugriff

Elementverweis-Operator ->
Der Operator bietet eine vereinfachte Syntax, um über Zeiger auf Klasseninstanzen
(inklusive Strukturen und Unions) auf deren Elemente zugreifen zu können.
pObjekt->element
● pObjekt: Zeiger auf eine Variable vom Typ Klasse, Struktur oder Union.
● element: ein Element.
struct person {
char name[20];
int plz;
};

int main() {
struct person p_leser;
strcpy(p_leser->name, "Otto");
p_leser->plz = 5100;
return 0;
}

Zeiger auf Klassenelemente ->*, .*


Die beiden Operatoren dienen dazu, Zeiger auf Klassenelemente zu dereferenzieren.
klassenobj.*p_classelement
p_klassentyp->*p_classelement
● p_classelement: Zeiger auf ein Element der Klasse T.
● klassenobj: Instanz der Klasse T oder einer von T abgeleiteten Klasse, von der
aus das Element der Basisklasse T eindeutig erreichbar ist.
● p_klassentyp: Zeiger auf Instanz der Klasse T oder einer von T abgeleiteten
Klasse, von der aus das Element der Basisklasse T eindeutig erreichbar ist.
#include <stdio.h>
#include <stdlib.h>

// Definition der Klasse


class extreme {
public:
// liefert Maximum der Parameter
int maximum(int var1, int var2)
{return ( (var1 > var2) ? var1 : var2);}
// liefert Minimum der Parameter
int minimum(int var1, int var2)
{return ( (var1 < var2) ? var1 : var2);}
};

int main() {
class extreme extr; // Instanzbildung
int extremum;
int wert1, wert2;
wert1 = rand()%20;
wert2 = rand()%40;

111
Sprachkonzepte und Syntax

// Definition der Zeiger auf Methoden


int (extreme::*z_max) (int, int);
int (extreme::*z_min) (int, int);

// Initialisierung der Zeiger


z_max = extreme::maximum;
z_min = extreme::minimum;

// Dereferenzierung der Zeiger zum Funktionsaufruf


extremum = (extr.*z_max) (wert1, wert2);
printf("Das Maximum von %d und %d ist %d\n",wert1,
wert2, extremum);
extremum = (extr.*z_min) (wert1, wert2);
printf("Das Minimum von %d und %d ist %d\n",wert1,
wert2, extremum);
return 0;
}

Bereichsoperator ::
Objekte und Funktionen gleichen Namens und gleicher Signatur (Parametertypen)
aus unterschiedlichen Gültigkeitsbereichen verdecken sich gegenseitig. Mittels des
Bereichsoperators kann aus dem aktuellen Gültigkeitsbereich auf verdeckte Varia-
blen und Funktionen anderer Gültigkeitsbereiche zugegriffen werden.
::global_name
Der unäre Operator dient dazu, auf verdeckte globale Variablen zugreifen zu kön-
nen (siehe erstes Beispiel).
space::name
In seiner binären Form wird der Operator eingesetzt, um
● auf bestimmte Namensbereiche zuzugreifen,
● auf statische Klassenelemente zuzugreifen,
● auf Basisklassenelemente zuzugreifen.
Der Zugriff funktioniert nur, wenn der Name eindeutig aufgelöst werden kann
(siehe zweites Beispiel).

Beispiele
Zugriff auf verdeckte, globale Variable:
#include <stdio.h>
int i = 1;
int main() {
int i = 2;
printf("i = %d\n",i); // lokales i verdeckt globales i
printf("i = %d\n",::i); // Zugriff auf globales i
return 0;
}

112
Bitweise Operatoren

Zugriff auf Variablen aus einem Namensbereich:


namespace space1 {
int i = 2;
}
class basis {
public:
int i;
void func()
{cout << space1::i;}; // Zugriff auf Namensbereich
};
class abgeleitet : public basis {
public:
int i;
void func()
{cout << basis::i;}; // Zugriff auf Basisklasse
};

Verweise
Siehe Kategorie Klassen, Zugriff von außerhalb der Klasse

Bitweise Operatoren
Beschreibung
Operatoren zur bitweisen Manipulation von Daten. Als Operanden sind allerdings nur Integer-
Werte erlaubt.

Anwendung
Mit Hilfe der Bit-Operatoren lassen sich bestimmte Programmieraufgaben sehr ele-
gant und effizient lösen. Voraussetzung für den sicheren Gebrauch der Operatoren
sind allerdings Kenntnisse über die Binärcodierung der manipulierten Daten.

bitweises UND &


Wenn der Operator »&« mit zwei Operanden benutzt wird, handelt es sich um den
bitweisen UND-Operator. Die Operanden können beliebige Integer-Werte sein.
Die beiden Operanden werden bitweise verglichen. Das Bit im Ergebnis wird nur
dann gesetzt, wenn in beiden Operanden die korrespondierenden Bits gesetzt sind.
Dieser Operator kann eingesetzt werden, um Bits in seinem ersten Operanden
gezielt zu löschen.
In der ASCII-Tabelle unterscheiden sich die Klein- von den Großbuchstaben des
englischen Alphabets (also nicht die deutschen Umlaute) binär dadurch, daß bei
den Kleinbuchstaben immer Bit 5 (von rechts her gezählt) gesetzt ist. Um einen

113
Sprachkonzepte und Syntax

Klein- in einen Großbuchstaben umzuwandeln, soll Bit 5 des ersten Operanden


gelöscht werden. Um dies zu erreichen, werden im zweiten Operanden, der Maske,
alle Bits, bis auf Bit 5, das gelöscht werden soll, gesetzt. Dadurch bleiben die ande-
ren Bits unverändert.
& 0110 0001 Buchstabe 'a'
& 1101 1111 Maske (dezimal 223)
& --------------------
& 0100 0001 Buchstabe 'A'

bitweises ODER |
Der Operator für die bitweise ODER-Verknüpfung »|« vergleicht die Bitmuster sei-
ner Operanden und setzt das entsprechende Bit im Ergebnis, wenn eines der Bits in
den Operanden gesetzt ist.
Dieser Operand kann beispielsweise dazu verwendet werden, um gezielt einzelne
Bits zu setzen, ohne die anderen Bits der ersten Operanden zu verändern.
Ein Beispiel dafür ist die Umwandlung von Groß- in Kleinbuchstaben. In der
ASCII-Tabelle unterscheiden sich die Klein- von den Großbuchstaben des engli-
schen Alphabets (also nicht die deutschen Umlaute) binär dadurch, daß bei den
Kleinbuchstaben immer Bit 5 gesetzt ist.
Um einen Großbuchstaben in den entsprechenden Kleinbuchstaben umzuwandeln,
braucht also nur Bit 5 gesetzt zu werden, was Sie im folgenden Beispiel sehen:
0100 0001 Buchstabe 'A'
| 0010 0000 Maske dezimal 32
--------------------
0110 0001 Buchstabe 'a'

bitweises exklusives ODER ^


Der Operator für die bitweise exklusive ODER-Verknüpfung vergleicht die Bitmu-
ster seiner Operanden und setzt das entsprechende Bit im Ergebnis, wenn eines der
Bits in den Operanden, aber nicht beide, gesetzt ist.
0001 1001
^ 0000 1100
----------------------
0001 0101

114
Bitweise Operatoren

bitweises Komplement ~
Der bitweise Komplement-Operator »~« kippt alle Bits seines Operanden. Durch
Invertierung werden im Ergebnis alle Bits, die im Operanden gesetzt waren,
gelöscht, und alle Bits, die gelöscht waren, gesetzt. Die Zahl 4 besitzt folgendes Bit-
muster:
0000 0100
Durch die Operation ~4 erhalten wir folgendes Muster:
1111 1011

Rechtsverschiebung >>
Bei der bitweisen Rechtsverschiebung werden die einzelnen Bits eines Operanden
um die festgelegte Anzahl nach rechts verschoben.
Der Operator kann beispielsweise für eine schnelle Programmierung der Division
durch die Potenzen der Zahl 2 benutzt werden.
Der Ausdruck 80 >> 3 entspricht 80 / 2^3 und erzeugt folgendes Ergebnis:

dezimal binär
vor Verschiebung 80 0101 0000
nach Verschiebung 10 0000 1010

Linksverschiebung <<
Bei der bitweisen Linksverschiebung werden die einzelnen Bits eines Operanden um
die festgelegte Anzahl nach links verschoben.
Der Operator kann beispielsweise für eine schnelle Programmierung der Multipli-
kation mit den Potenzen der Zahl 2 benutzt werden.
Der Ausdruck 3 << 2 entspricht 3 * 2^2 und erzeugt folgendes Ergebnis:

dezimal binär
vor Verschiebung 3 0000 0011
nach Verschiebung 12 0000 1100

Beispiele
#include <stdio.h>
int main() {
printf(" a & 223 = %c\n", 'a' & 223);
printf(" A | 0x20 = %c\n", 'A' | 0x20);
printf(" 25 ^ 12 = %d\n", 25 ^ 12);
printf(" 3 << 2 = %d\n", 3 << 2);

115
Sprachkonzepte und Syntax

printf(" 80 >> 3 = %d\n", 80 >> 3 );


printf("~4 = %d\n", ~4);
return 0;
}
Das Programm erzeugt folgende Ausgabe:
a & 223 = A
A | 0x20 = a
25 ^ 12 = 21
3 << 2 = 12
80 >> 3 = 10
~4 = -5

Verweise
Siehe Streamoperatoren

Streamoperatoren
Beschreibung
In C++ sind die Operatoren >> und << für das formatierte Einlesen und Schreiben von und in
Streams überladen.

Anwendung
Der Einsatz der Streamoperatoren für die Ein- und Ausgabe ist recht komfortabel
und sehr übersichtlich.
int wert = 3;
cout << "Wert = " << wert << endl; // cout ist der Standardausgabestream
Die Programmierung mit Streamoperatoren ist zudem in vorbildlicher Weise
objektorientiert:
● die Streamoperatoren sind standardmäßig für alle elementaren Datentypen
überladen (int, float, char, etc.).
● durch Überladung kann das Einsatzgebiet der Operatoren auf selbst definierte
Klassentypen ausgedehnt werden.
Durch sogenannte Manipulatoren kann die Formatierung der Ein- und Ausgabe
gesteuert werden.

Beispiele
int wert;
cout << "Geben Sie einen Wert ein:" << endl;
cin >> wert;
cout << left;
cout << "Wert = " << wert << endl;

116
Die Operatoren new und delete

Verweise
Siehe Referenz der C++-Laufzeitbibliothek, Header-Dateien iostream, iomanip, etc.

Die Operatoren new und delete


Beschreibung
Die Operatoren new und delete dienen zur dynamischen Speicherverwaltung und können in
C++-Programmen die Funktionen malloc() und free() ersetzen.
Intern sind die Operatoren meist mit Hilfe der Funktionen malloc() und free()
implementiert, sie erlauben aber eine einfachere und erweiterte Handhabung.

new-Operator new
Der new-Operator dient zur dynamischen Speicherallokation. Für die Implementie-
rung des Operators sind im ANSI C++-Standard allein 6 Operatorfunktionen vor-
gesehen.
Die verschiedenen Operatorfunktionen sind für die Unterscheidung von einfachen
Objekten und Arrays als Operanden, und für die einfache Steuerung der Fehlerbe-
handlung und die Zuweisung eines bestimmten Speicherbereiches gedacht.
Zudem gibt es zwei Formen des Aufrufs, je nachdem, ob die Typangabe geklam-
mert wird oder nicht. Dies ist notwendig, um in Typangaben, die Operatoren wie
&, * oder [] enthalten, unterscheiden zu können, ob die Deklarations- oder die
Zuweisungsoperatoren gemeint sind:
new [freie_arg] Typ [initialisierer]
new [freie_arg] (Typ) [initialisierer]
● freie_arg: Argumentenliste, die überladenen Formen übergeben werden kann.
● Typ: Datentyp, der für den Speicher zu reservieren ist.
● initialisierer: Wert, der benutzt wird, den reservierten Speicherplatz zu initiali-
sieren.

Beispiel
1: long double *p, *q, **pp;
2: p = new long double;
3: pp = new long double*;
4: p = new long double(1.2);
5: //q = new long double * 3;
6: q = new long double [3];
7: //q = new long double [3](1,2,3);
8: class demo {
9: int i;
10: } *p_demo;

117
Sprachkonzepte und Syntax

11: p_demo = new demo[10];


12: void (**func_ptr)(int);
13: //func_ptr = new void(*[3])(int);
14: func_ptr = new (void(*[3])(int));
15: char ziel[sizeof(demo)];
16: p_demo = new (ziel) demo;

Erläuterung
In Zeile 2 wird ein Zeiger auf Objekte des Datentyps long double eingerichtet, in
Zeile 3 ein Zeiger auf einen Zeiger auf Objekte des Datentyps long double.
In Zeile 4 wird der Zeiger p eingerichtet und der Speicherbereich, auf den der Zei-
ger p verweist, mit dem Wert 1.2 initialisiert.
In Zeile 5 wird versucht, einen Zeiger auf ein Array von 3 long double Werten ein-
zurichten. Die verwendete Syntax ist ähnlich dem Gebrauch der Funktion malloc(),
führt hier aber zu Fehlern, da der Compiler den Aufruf als (new long double)*3 ver-
steht.
In Zeile 6 erfolgt die korrekte Allokation des Arrays.
Zeile 7: syntaktisch korrekt, aber Arrays können nicht initialisiert werden.
In Zeile 11 wird ein Array von Klassenobjekten eingerichtet.
In Zeile 12 wird ein Zeiger func_ptr auf Funktionszeiger deklariert. Danach soll für
den Zeiger func_ptr Speicher für ein Array von Funktionszeigern reserviert werden,
dessen erstes Element ihm als Adresse übergeben wird. Die Zuweisung in Zeile 13
führt wie in Zeile 5 zu einem Interpretationsfehler. In Zeile 14 wird daher die
zweite Syntaxform gewählt, bei der die Typangabe eingeklammert ist.
In Zeile 15 wird Speicher von der Größe eines demo-Objekts reserviert. In Zeile 16
wird das demo-Objekt in dem Speicherbereich, auf den ziel verweist, eingerichtet
(Plazierungsform des Operators).

Warnung
● Objekte, die mit new eingerichtet wurden, haben unbegrenzte Lebensdauer.
Der Speicherplatz muß daher mittels des delete-Operators wieder freigegeben
werden.
● Wird Speicher für ein Array reserviert, liefert der new-Operator einen Zeiger
auf das erste Array-Element zurück.
● Bei der Reservierung von Arrays müssen alle Dimensionen durch konstante,
positive Ausdrücke angegeben werden; die erste Dimension kann durch einen
allgemeinen Ausdruck spezifiziert werden.
● Arrays können nicht initialisiert werden.

118
Typumwandlung und -identifizierung

● Klassenobjekte können nur mit new eingerichtet werden, wenn die Klasse einen
Standardkonstruktor besitzt, oder die Argumente für den Konstruktor dem
Operator übergeben werden.
● Referenzen können nicht mit new eingerichtet werden, da sie keinen Speicher-
platz haben.
● Der Operator berechnet den Speicherbedarf für den einzurichtenden Datentyp
selbst, weswegen der erste Parameter einer new-Operatorfunktion immer vom
Typ size_t ist (zu beachten bei Überladung).
● Wird der new-Operator überladen, sollte auch eine entsprechende Form des
delete-Operators implementiert werden.

delete-Operator delete
Der delete-Operator dient zur dynamischen Freigabe von mittels new allokiertem
Speicher.
delete p_objekt
delete [] p_objekt

Warnung
● Zeiger auf Konstanten können nicht gelöscht werden.
● Für Klassen wird beim Löschen der Destruktor aufgerufen.
● Die zweite Version ist zur Freigabe von Arrays. Die Dimension wird dabei
nicht angegeben.
● Aufrufe mit Nullzeigern sind ohne Effekt.

Beispiele
class demo *p;
p = new demo[10];
delete[] p;
int **p;
p = new int*;
delete p;

Typumwandlung und -identifizierung


Beschreibung
Mit Hilfe der Operatoren zur Typumwandlung kann man – innerhalb bestimmter Grenzen –
Werte und Objekte eines Datentyps in einen anderen Datentyp umwandeln.
Mit Hilfe des typeid-Operators kann man in C++ den Typ eines Klassenobjekts zur Laufzeit fest-
stellen.

119
Sprachkonzepte und Syntax

Anwendung
Gelegentlich ist es wünschenswert, daß eine Variable eines bestimmten Datentyps
als einem anderen Datentyp angehörig behandelt wird. Sofern eine solche Typum-
wandlung durchführbar ist, kann sie durch den C-Cast-Operator () oder die C++-
Operatoren const_cast, dynamic_cast, static_cast und reinterpret_cast, die als
Schlüsselworte in die Sprache aufgenommen sind, explizit herbeigeführt werden.
Die C++-Operatoren sind vor allem dazu gedacht, die verschiedenen Konvertierun-
gen (die auch mit dem Cast-Operator () vorgenommen werden könnten) nach
ihrem Gefahrenpotential und dem Einsatzgebiet zu kategorisieren. Bei Auftreten
eines Fehlers kann der Programmierer dann eventuell aus der Art des Fehlers auf
die betreffende Typumwandlung schließen und mit Hilfe der Suchfunktion seines
Editors schnell zu allen Vorkommen des jeweiligen Operators springen.

Operator Beschreibung
static_cast<Typ>(var) Zur Umwandlung zwischen »nahe verwandten« Typen –
also alle Fälle, in denen der Compiler auch eine implizite
Konvertierung vornehmen könnte, plus einige einfache
Sonderfälle.
reinterpret_cast<Typ>(var) Für fast alle anderen erlaubten Umwandlungen.
const_cast<Typ>(var) Entfernt eine const- oder volatile-Deklaration aus ei-
nem Typ.
dynamic_cast<Typ>(var) Zur Umwandlung zwischen Zeigern oder Referenzen auf
Klassentypen einer gemeinsamen Klassenhierarchie

Der Cast-Operator ()
Der Cast-Operator kann benutzt werden, um in einer Anweisung den Typ des Aus-
drucks der rechten Seite in den Typ des Bezeichners der linken Seite umzuwandeln:
bezeichner1 = (Typ_von_bezeichner1) AUSDRUCK;
bezeichner1 = (Typ_von_bezeichner1) bezeichner2;
Eine zweite Form der Syntax wandelt den Typ einer Variablen direkt um
bezeichner = Datentyp();

Beispiele
intptr = (int *) malloc(80 * sizeof(int));
printf("%f\n", (double) 13/2);
int i = int(3.14);
int i = int(); // weist undefinierten Wert zu

120
Typumwandlung und -identifizierung

Typumwandlung const_cast (nur C++)


Der Operator const_cast dient dazu, die Qualifizierer const und volatile aus einer
Typangabe zu entfernen oder gegeneinander auszutauschen. Den Operator const_cast
kann man beispielsweise dazu nutzen, um eine Variable, die durch const-Deklaration
grundsätzlich vor ungewollter Überschreibung geschützt wurde, für eine nachfol-
gende Zuweisung veränderbar zu machen.
const_cast < Zieltyp > (variable)
● Zieltyp: Angabe des Typs, in den die variable umgewandelt werden soll. Der
Zieltyp muß mit dem Typ der variable bis auf die Qualifizerer const oder vola-
tile übereinstimmen.
● variable: Umzuwandelndes Objekt.

Beispiele
const int* p;
int* q;
p = q; // korrekt: Zuweisung eines int*-Objekts
// an const int*
q = p; // Fehler: const int* an int*
q = const_cast <int*> (p); // ok.

Typumwandlung dynamic_cast (nur C++)


Der dynamic_cast-Operator kann dazu verwendet werden, Zeiger (oder Referenzen)
auf Objekte einer Basisklasse in Zeiger (oder Referenzen) auf Objekte einer abgelei-
teten Klasse umzuwandeln oder vice versa.
UpCast. In einem Objekt einer abgeleiteten Klasse sind die Elemente der Basisklas-
sen praktisch als Teilobjekte enthalten. Ist T eine solche eindeutige public Basis-
klasse, kann ein Zeiger auf das Gesamtobjekt der abgeleiteten Klasse in einen Zei-
ger auf das Teilobjekt der Basisklasse umgewandelt werden (gleiches gilt für
Referenzen). Dieser Vorgang gehört zu den Standardkonvertierungen von C++ und
erfordert an sich nicht den Einsatz des dynamic_cast-Operators.
DownCast. Umgekehrt kann ein Zeiger auf ein Basisklassenobjekt, das Teil eines
abgeleiteten Objekts ist, in einen Zeiger auf das abgeleitete Objekt zurückverwan-
delt werden, wenn es sich um eine polymorphe Basisklasse (Klasse, die virtuelle
Methoden enthält) handelt. (Für nicht polymorphe Basisklassen kann man den
static_cast-Operator verwenden.)
class_zeiger1 = dynamic_cast < Zieltyp > (class_zeiger2)
● class_zeiger1: Zeiger oder Referenz auf Klassenobjekt, dem der umgewandelte
Zeiger (Referenz) class_zeiger2 zugewiesen wird.
● Zieltyp: Angabe des Typs, in den class_zeiger2 umgewandelt werden soll (Typ
von class_zeiger1 oder void* ).
● class_zeiger2: Umzuwandelnder Zeiger (Referenz).

121
Sprachkonzepte und Syntax

Beispiele
#include <iostream>
using namespace std;
class Basis {
public:
virtual void func() {cout << "basisklasse" << endl;}
};
class Abgeleitet : public Basis {
public:
void func_abg() {cout << "abgeleitete Klasse" << endl;}
};

int main() {
Abgeleitet *p_abg = new Abgeleitet;
Basis *p_bp = new Basis;

// Umwandlung Zeiger auf abgeleitete Klasse zu Basisklasse


// p_bp = p_abg; ginge auch
p_bp = dynamic_cast <Basis*> (p_abg);
if(p_bp != NULL)
p_bp->func_abg(); // Fehler

// Umwandlung Zeiger auf Basisklasse in abgeleitete Klasse


// p_abg = p_bp; nicht möglich
p_abg = dynamic_cast <Abgeleitet*> (p_bp);
if(p_abg != NULL)
p_abg->func_abg(); // o.k.
return 0;
}
Zudem kann man unter bestimmten Voraussetzungen mit dynamic_cast auch einen
CrossCast von einer Basisklasse in eine andere Basisklasse bewirken. Im Fehlerfall
wird für Referenzen eine bad_cast-Exception ausgelöst und für Zeiger ein NULL-
Zeiger zurückgeliefert.

Typumwandlung static_cast (nur C++)


Mit dem Operator static_cast können alle gängigen Konvertierungen explizit vor-
genommen werden. Darüber hinaus erlaubt er eine Konvertierung eines Zeigers auf
eine nicht-polymorphe Basisklasse in eine ihrer abgeleiteten Klassen, und ergänzt
hierin den Operator dynamic_cast.
bezeichner1 = static_cast < Zieltyp > (bezeichner2)
● bezeichner1: Objekt, dem das umgewandelte Objekt bezeichner2 zugewiesen
wird.
● Zieltyp: Angabe des Typs, in den bezeichner2 umgewandelt werden soll.
● bezeichner2: Umzuwandelndes Objekt.

122
Typumwandlung und -identifizierung

Beispiele
#include <iostream>
using namespace std;
class Basis {
public:
void func() {cout << "basisklasse" << endl;}
};
class Abgeleitet : public Basis {
public:
void func_abg() {cout << "abgeleitete Klasse" << endl;}
};

int main() {
Abgeleitet *p_abg = new Abgeleitet;
Basis *p_bp = new Basis;

// Umwandlung Zeiger auf abgeleitete Klasse zu Basisklasse


p_bp = dynamic_cast <Basis*> (p_abg);
if(p_bp == NULL)
cout << "cast gescheitert" << endl;
else
p_bp->func_abg(); // Fehler
// Umwandlung Zeiger auf Basisklasse in abgeleitete Klasse
p_abg = static_cast <Abgeleitet*> (p_bp);
if(p_abg == NULL)
cout << "cast gescheitert" << endl;
else
p_abg->func_abg(); // o.k.
return 0;
}

Typumwandlung reinterpret_cast (nur C++)


Der Operator reinterpret_cast ist für besonders kritische Konvertierungen gedacht,
beispielsweise die Konvertierung von Integer-Typen in Zeiger und vice versa, sowie
zur Konvertierung von Zeigern auf Funktionen.
bezeichner1 = reinterpret_cast < Zieltyp > (bezeichner2)
● bezeichner1: Objekt, dem das umgewandelte Objekt bezeichner2 zugewiesen
wird.
● Zieltyp: Angabe des Typs, in den bezeichner2 umgewandelt werden soll.
● bezeichner2: Umzuwandelndes Objekt.

123
Sprachkonzepte und Syntax

Warnung
● Werden Integer-Typen in Zeiger umgewandelt oder umgekehrt, ist nicht si-
chergestellt, daß der Wert des konvertierten Objektes korrekt interpretiert
werden kann.
● Es ist allerdings sichergestellt, daß bei einer nachfolgenden Rückkonvertierung
der ursprüngliche Wert wieder erscheint (natürlich vorausgesetzt, daß zwi-
schen den Konvertierungen keine Zuweisung an die Variable erfolgte).
● Entsprechendes gilt, wenn Zeiger auf Funktionen in Zeiger auf Funktionen an-
deren Typs oder in Zeiger auf Objekte umgewandelt werden.
● Werden Zeiger oder Referenzen konvertiert, sind undefinierte Klassenbezeich-
ner in der Typangabe erlaubt.

Typidentifizierung typeid
Der Operator typeid erzeugt für das ihm übergebene Objekt eine entsprechende
Instanz der Klasse type_info (definiert in typeinfo). In dieser Instanz, die vom Ope-
rator als Referenz zurückgeliefert wird, sind Informationen zum Datentyp des
übergebenen Objekts abgelegt. Die type_info-Objekte können direkt mit Hife der
Operatoren == und != verglichen werden. Zudem kann die Methode name() aufge-
rufen werden, die einen String zurückliefert, der den Typ des typeid-Operanden
identifiziert.

Warnung
Laut ANSI-Standard sind Typen, die sich nur in den CV-Qualifizierern unterschei-
den (const, volatile) identisch. Einige Compiler differenzieren hier aber.

Beispiele
#include <iostream>
#include <typeinfo>
using namespace std;

class demo {int wert;};

int main() {
demo d1();
const demo d2();

if(typeid(d1) == typeid(d2))
cout << "gleich" << endl;
if(typeid(d1).name() == typeid(d2).name())
cout << typeid(d1).name() << endl;

return 0;
}

124
Sonstige Operatoren

Sonstige Operatoren
sizeof-Operator sizeof
Der sizeof-Operator liefert als Ergebnis die Größe seines Operanden in Byte
zurück. Der Rückgabewert ist vom vorzeichenlosen Integer-Typ size_t. Als Ope-
rand kann sowohl ein Datentyp als auch eine Variable übergeben werden.
Typische Einsatzgebiete für den sizeof-Operator sind Speicherbedarfberechnungen
für die dynamische Speicherallokation sowie die Berechnung der Anzahl an Ele-
menten in einem Array.

Warnung
● Für Referenzen liefert der sizeof-Operator die Größe des referenzierten Ob-
jektes.
● Nicht zulässig sind: Funktionen, Bitfelder, undefinierte Klassen, Arrays mit
fehlender Dimensionsangabe sowie der Typ void.
● Wenn einer der Typen char, unsigned char oder signed char als Argument ver-
wendet wird, ist das Ergebnis per Definition immer 1.
● Die Größe eines Zeichenliterals (sizeof('Z')) entspricht in C der Größe von
int, in C++ der Größe von char.
● Wird sizeof auf ein Array angewendet, ist das Ergebnis die Gesamtgröße des
Arrays in Bytes. Doch Vorsicht! Wenn sizeof innerhalb einer Funktion benutzt
wird, um die Größe eines Arrays zu ermitteln, das an einen Parameter der
Funktion übergeben wurde, liefert sizeof die Größe des Zeigers auf das Array
zurück, da Arraynamen als Zeiger übergeben werden.
● Handelt es sich beim Argument um eine Klasse, Struktur oder Union, wird die
tatsächliche Größe zurückgegeben, in der auch Füllbytes zur Ausrichtung an
Speichergrenzen enthalten sein können. Das Ergebnis der sizeof-Operation
kann dann von der Summe des Speicherplatzbedarfs der einzelnen Elemente
verschieden sein.

Beispiele
int main() {
int feld[123];

// liefert anz = 123;


int anz = sizeof(feld)/sizeof(int);
// reserviert Feld für 123 double-Werte
double *ptr = (double*) malloc(anz*sizeof(double));

return 0;
}

125
Sprachkonzepte und Syntax

Adreß-Operator &
Wenn der Operator »&« mit einem Operanden benutzt wird, liefert er die Adresse
seines Operanden zurück. Als Operand kann jeder Bezeichner eingesetzt werden,
der einen L-Wert verkörpert.

Warnung
● Der Operator kann nicht auf das Element eines Bitfeldes oder auf ein Objekt,
das mit der Speicherklasse register definiert wurde, angewendet werden.
● Funktions- und Array-Namen können direkt als Adressen interpretiert wer-
den, weswegen für sie die Anwendung des Adreß-Operators nicht erforderlich
ist.

Beispiele
// Integer-Wert von Tastatur einlesen
int zahl;
scanf("%d", &zahl);

// Zeiger auf eine Variable richten


int zahl_wert;
int *zahl_zeiger;
zahl_zeiger = &zahl_wert;

// Uebergabe der Funktion demo() an func()


void demo() {...}
void func(int* i, void (*f)() ) {...}
func(&zahl_wert, demo);

Bedingungs-Operator (bedingte Bewertung) ?:


ANSI C/C++ kennt einen einzigen ternären Operator, der auch Bedingungs-Opera-
tor genannt wird. Der Bedingungs-Operator (?:) ist eigentlich eine Kurzform der
if-else-Anweisung. Das allgemeine Format dieses Operators lautet folgender-
maßen:
Bedingung ? Ausdruck1 : Ausdruck2

Auswertung
● Wenn die Auswertung der Bedingung nicht 0 (also wahr) ergibt, wird
Ausdruck1 ausgeführt.
● Ergibt die Auswertung der Bedingung 0 (also unwahr), wird Ausdruck2 ausge-
wertet.

126
Sonstige Operatoren

Beispiele
int max, eins, zwei;
eins = 1;
zwei = 2;
max = (eins > zwei) ? eins : zwei;
Die gleiche Zuweisung kann auch als if-else-Anweisung formuliert werden:
if (eins > zwei)
max = eins;
else
max = zwei;

Sequentielle Auswertung (Komma-Operator) ,


Wenn das Zeichen »,« nicht eine Liste von Elementen trennt (Funktionsparameter,
Initialisierungswerte etc.), dient es zur sequentiellen Auswertung. Er wird üblicher-
weise an Stellen verwendet, an denen nur ein Ausdruck erlaubt ist, um zwei oder
mehr Ausdrücke auszuwerten.

Warnung
● Das Ergebnis der durch den Komma-Operator getrennten Ausdrücke hat den
gleichen Wert und Typ wie der rechte Operand.
● Die Operanden können einen beliebigen Typ besitzen; Typumwandlungen
werden nicht durchgeführt.
● In Listen müssen die entsprechenden Ausdrücke geklammert werden.

Beispiele
func(int par1, float par2) {..};
Das nächste Beispiel verwendet den Komma-Operator im Reinitialisierungsteil
einer for-Schleife, um bei jedem Schleifendurchlauf nicht nur eine, sondern beide
Schleifenvariablen i und j zu inkrementieren.
for (i=j=0; i<MAXWERT; i++, j++) { ...
Im dritten Beispiel wird zuerst der linke Operand (i++) ausgewertet. Anschließend
wird das Ergebnis von zahl2/4 der Variablen zahl1 zugewiesen.
zahl1 = (i++, zahl2 / 4);
Wird der Operator in Listen eingesetzt, müssen die Anweisungen geklammert wer-
den.
func(i, (f=3.14, f+0.0015));

127
Sprachkonzepte und Syntax

Synonyme
In C++ wurden für einige Operatoren synonyme Bezeichnungen eingeführt.

Synonym Operator
bitand &
and &&
bitor |
or ||
xor ^
compl ~
and_eq &=
or_eq |=
xor_eq ^=
not !
not_eq !=

Priorität und Assoziativität


Beschreibung
Um vorhersagen zu können, wie ein Ausdruck ausgewertet wird, müssen Sie wissen, wie der
Compiler Ausdrücke auswertet.
Priorität Jeder Operator gehört einer bestimmten Prioritätsklasse an. In einem Ausdruck
werden die Operatoren in der Reihenfolge ihrer Priorität abgearbeitet, wobei
Operatoren höherer Priorität zuerst ausgewertet werden.
Assoziativität Gibt es in einem Ausdruck mehrere Operatoren gleicher Priorität, werden diese
in der für die Operatoren charakteristischen Richtung abgearbeitet.
Operanden In welcher Reihenfolge die Operanden eines binären Operatoren ausgewertet
werden, ist nicht festgelegt (meist wird zuerst der linke, dann der rechte Operand
ausgewertet).
Für die logischen Operatoren ist vorgeschrieben, daß der linke Operand zuerst
ausgewertet wird. Ist der linke Operand eines &&-Operators gleich 0 (false),
wird der rechte Operand nicht mehr ausgewertet. Gleiches gilt für den ||-Opera-
tor, wenn der linke Operand gleich 1 (true) ist.
Klammern Durch das Setzen von Klammern kann man die Reihenfolge, in der die Operato-
ren abgearbeitet werden, beeinflussen.
Priorität und Assoziativität der einzelnen Operatoren können Sie der nachfolgenden Tabelle
entnehmen.

128
Überladung von Operatoren

Priorität Operator Assoziativität


18 :: (expr)
17 [] -> . L-R
Postfix: ++ --
typeid, cast-Operatoren
16 unär: + – * ! ~ & () R-L
Präfix: ++ --
new, delete, sizeof
15 .* ->* L-R
14 */% L-R
13 binär: + - L-R
12 << >> L-R
11 < <= > >= L-R
10 == != L-R
9 & (bitand) L-R
8 ^ (xor) L-R
7 | (bitor) L-R
6 && L-R
5 || L-R
4 = *= /* %= += – = <<= >>= R-L
&= |= ^=
3 ?: R-L
2 throw L-R
1 , L-R

Überladung von Operatoren


Beschreibung
Die Überladung von Operatoren wird eingesetzt, um das Verhalten eines Operators an die ihm
übergebenen Operanden anzupassen. Der Vorteil für den Programmierer besteht darin, daß er
die zur Verfügung stehenden Operatoren für eigene Datentypen, genauer gesagt Klassen,
umdefinieren kann. Ein Laufzeitvorteil ergibt sich dadurch nicht, da sich hinter den über-
ladenen Operatoren Funktionen verbergen.

129
Sprachkonzepte und Syntax

Anwendung
Operatoren können innerhalb der Deklaration ihrer Klasse oder außerhalb im
Dateibereich überladen werden.
Bei Überladung im Klassenbereich ist der erste Operator automatisch ein Objekt
der Klasse und wird bei der Definition der Operatorfunktion nicht mehr als Para-
meter aufgeführt. Im Klassenbereich überladene Operatoren haben Zugriff auf die
private und protected Elemente der Klasse (siehe nachfolgende Beispiele).
Bei Überladung im Dateibereich müssen alle Operanden bei der Definition der
Operatorfunktion als Parameter aufgeführt werden. Im Dateibereich überladene
Operatoren haben keinen Zugriff auf die private und protected Elemente der
Klasse. Man kann dem aber abhelfen, indem man die Operatorfunktion in der
Klasse als friend deklariert (siehe Überladung der Stream-Operatoren).
Operatoren, die aneinandergereiht werden können (beispielsweise var1 = var2 =
var3;), müssen dazu eine Referenz auf ihren linken Operanden als Rückgabewert
zurückliefern.

Warnung
● Es können keine neuen Operatoren definiert werden.
● Folgende Operatoren können nicht überladen werden: ::, ?:, ., .*, #, ##, defi-
ned, typeid, die C++-Cast-Operatoren.
● Folgende Operatoren können nur in einem Klassenbereich überladen werden:
=, (), [], -> .
● Mindestens ein Operand eines überladenen Operators muß eine Klasse oder
eine Referenz auf eine Klasse sein. (Die Funktionsweise der Operatoren für die
elementaren Datentypen kann also nicht geändert werden.)
● Die allgemeine Auslegung des Operators (Anzahl Operanden, Priorität, Vorga-
beargumente) kann nicht verändert werden.

Überladung unärer Operatoren


Unäre Operatoren, die außerhalb des Klassenbereichs überladen werden, erwarten
die Übergabe eines Operanden vom Klassentyp. Unäre Operatoren, die innerhalb
einer Klasse überladen werden, dürfen nur durch nicht-statische Elementfunktionen
ohne Parameter überladen werden. Die aufrufende Klasseninstanz wird automa-
tisch als Operand genommen.
Syntax: Deklaration in Klasse
Rückgabetyp operator @() {} // @ gleich !, ++, --, ...
Syntax: Deklaration in Dateibereich
Rückgabetyp operator @(Klassentyp) {} // @ gleich !, ++, --, ...

130
Überladung von Operatoren

Beispiele
class person {
int alter;
public:
...
operator ++ () { //Praefix-Inkrement
++alter;
return *this;
}
};
Die Deklaration eines int-Parameters für den Postfix-Inkrement-Operator spezifi-
ziert keinen wirklichen zweiten Operanden, sondern dient nur zur Unterscheidung
vom Präfix-Inkrement-Operator.

Überladung binärer Operatoren


Binäre Operatoren, die außerhalb des Klassenbereichs überladen werden, erwarten
die Übergabe beider Operanden. Einer der Operanden muß ein Klassentyp sein.
Binäre Operatoren, die innerhalb einer Klasse überladen werden, dürfen nur durch
nicht-statische Elementfunktionen mit einem Parameter überladen werden. Die auf-
rufende Klasseninstanz wird automatisch als erster Operand genommen.

Beispiele
class person { .. };
class adressbuch {
/* enthält als Datenelemente eine Menge von person-Einträgen,
die nicht als statisches Array, sondern als
dynamische Liste oder Baum verwaltet werden */
...
public:
person& operator[] (int);
};
person& adressbuch::operator[] (int i) {
class person *gefunden;
/* durchsucht dynamische Struktur */
...
return *gefunden;
};

int main() {
class adressbuch persoenlich;
class person eintrag;
...
eintrag = persoenlich[3];
return 0;
}

131
Sprachkonzepte und Syntax

Programmsteuerung

Programmsteuerung
Beschreibung
Je komplexer Programme werden, desto öfter ist es erforderlich, je nach Situation und Zustand
des Programms zu verschiedenen Anweisungen zu verzweigen.
Zur Steuerung des Programmflußes gibt es veschiedene Konzepte:
– Verzweigungen
– Schleifen
– Exceptions
– Bedingte Kompilation

Anwendung
● Verzweigungen. Verzweigungen ermöglichen es dem Programmierer, einen
oder mehrere Anweisungsblöcke nur in Abhängigkeit von bestimmten Bedin-
gungen ausführen zu lassen.
● Schleifen. Schleifen ermöglichen es dem Programmierer, einen Anweisungs-
block mehrmals hintereinander ausführen zu lassen.
● Exceptions. Exeptions und das Konzept der Exceptions-Behandlung ermögli-
chen es einem Programmierer, die Fehlerbehandlung weitgehend von dem Pro-
grammfluß des eigentlichen Programmcodes zu trennen. Dazu gehört auch,
daß der Ort der Fehlerentstehung nicht mehr mit dem Ort der Fehlerbehand-
lung zusammenfallen muß.
● Bedingte Kompilation. Mit Hilfe von Präprozessor-Direktiven kann der Pro-
grammierer steuern, welche Codeblöcke in Abhängigkeit von Präprozessor-
Schaltern kompiliert und in das ausführbare Programm aufgenommen werden
sollen und welche nicht.

Die if-Bedingung
Beschreibung
Die if-Bedingung kontrolliert, ob eine nachfolgende Anweisung oder ein Anweisungsblock
ausgeführt wird oder nicht.

132
Die if-else-Verzweigung

Anwendung
Auf das Schlüsselwort if folgt in Klammern eine Bedingung. Bei Ausführung des
Programms wird diese Bedingung ausgewertet. Ergibt die Bewertung das Ergebnis
true (also einen Wert ungleich Null), wird die zu if gehörende Anweisung ausge-
führt. Liefert die Auswertung des Ausdrucks als Ergebnis false, wird die Ausfüh-
rung des Programms mit der ersten Anweisung hinter der Verzweigung fortgesetzt.

Syntax
if (Bedingung) if (Bedingung)
Anweisung; {
Anweisungsblock;
}
● Bedingung: Die Bedingung, die ausgewertet wird, muß einen booleschen Wert
ergeben. Hier kann beispielsweise eine Ganzzahl, eine arithmetische Operati-
on, ein Vergleich oder der Aufruf einer Funktion mit entsprechendem Rückga-
betyp stehen.
● Anweisung/Anweisungsblock: Auf die if-Bedingung kann eine einzelne An-
weisung oder ein Anweisungsblock folgen. Eine einzelne Anweisung muß im-
mer mit einem Semikolon (dem Anweisungsbegrenzer) beendet werden. Wenn
ein Anweisungsblock ausgeführt werden soll, muß dieser in geschweifte Klam-
mern eingeschlossen werden.

Warnung
Nie ein Semikolon hinter die Bedingung setzen. Dies würde der Compiler als eine
leere Anweisung interpretieren. Die if-Bedingung bezöge sich dann nur auf diese
leere Anweisung.

Beispiele
if (cZeichen == 'a')
printf("Das Zeichen ist a.");
if ( isdigit(cZeichen) )
printf("Das Zeichen ist eine Zahl");

Die if-else-Verzweigung
Beschreibung
Die if-else-Verzweigung regelt, welcher von zwei Anweisungsblöcken in Abhängigkeit von
einer Bedingung ausgeführt werden soll.

133
Sprachkonzepte und Syntax

Anwendung
Die einfache if-Bedingung kann nur steuern, ob ein einzelner Anweisungsblock
ausgeführt werden soll oder nicht. Es gibt aber auch Fälle, in denen man – je nach-
dem, ob die Bedingung true oder false ergibt – den einen oder anderen Anwei-
sungsblock ausführen möchte.
Diese Sprachkonstruktion wird durch das Schlüsselwort else eingeleitet.
if (Bedingung) if (Bedingung)
Anweisung; { Anweisungsblock }
else else
Anweisung; { Anweisungsblock }

Beispiele
if (cZeichen == 'a')
printf("Das Zeichen ist a.");
else
printf("Das Zeichen ist nicht a.");

if-else-Ketten
Beschreibung
Sprachkonstrukte, in denen der else-Teil einer if-else-Verzweigung selbst wiederum eine if-
else-Verzweigung ist.

Anwendung
Mit den Schlüsselworten if und else ist es möglich, sogenannte else-if-Ketten zu
erstellen, bei denen mehrere Ausdrücke überprüft werden können.
if (Bedingung)
Anweisung;
else if (Bedingung)
Anweisung;
else if (Bedingung)
Anweisung;
else
Anweisung;

Auswertung der else-if-Ketten


Die Bedingungen werden in der Reihenfolge ausgewertet, in der sie im Programm-
code stehen. Wenn eine der Bedingungen als Ergebnis true liefert, wird der zugehö-
rende Anweisungsteil ausgeführt und damit die Abarbeitung der Kette beendet. Die
zum letzten else gehörenden Anweisungen werden ausgeführt, wenn keine der vor-
her überprüften Bedingungen das Ergebnis true liefert.

134
switch-Verzweigung

Beispiele
printf("Geben Sie ein: Zahl Operator Zahl <Return>\n");
scanf("%f %c %f", &zahl1, &Operator, &zahl2);
if (Operator == '+')
printf("= %f", zahl1 + zahl2);
else if (Operator == '-')
printf("= %f", zahl1 – zahl2);
else if (Operator == '*')
printf("= %f", zahl1 * zahl2);
...

Verweise
Siehe switch-Verzweigung

switch-Verzweigung
Beschreibung
Komplexe Sprunganweisung, die in Abhängigkeit von einem Ausdruck zu verschiedenen Ein-
sprungmarken in einen Anweisungsblock verzweigt.

Anwendung
Eine einfachere und meist auch übersichtlichere Programmiertechnik als die im
vorigen Abschnitt beschriebenen if-else-Ketten bietet die switch-Anweisung. Auch
mit ihr kann ein Programm zwischen mehreren Alternativen auswählen – allerdings
i.G. zur if-else-Kette nur in Abhängigkeit vom Wert eines Ausdrucks.
switch(Ausdruck)
{
case Konstante1: Anweisung;
break;
case Konstante2: Anweisung;
break;
case Konstante3: Anweisung;
break;
case Konstante4: Anweisung;
break;
default: Anweisung;
}
● Ausdruck: Ausdruck ist ein ganzzahliger Wert (auch Aufzählungstyp), der mit
allen innerhalb der switch-Anweisung stehenden case-Marken verglichen wird.
Hier kann auch der Aufruf einer Funktion stehen, die eine Ganzzahl als Ergeb-
nis zurückgibt. Gleichzeitig kann hier, wie bei der if-Anweisung, eine Zuwei-
sung des Funktionsergebnisses erfolgen.
● case Konstante: Konstanten, die mit dem Ausdruck verglichen werden.

135
Sprachkonzepte und Syntax

● Anweisung: Anweisung wird ausgeführt, wenn die zugehörende Konstante und


der switch-Ausdruck identisch sind. Wenn einmal eine Übereinstimmung ge-
funden wurde, werden alle Anweisungen (auch die zu anderen Konstanten
gehörenden) ausgeführt, bis entweder das Schlüsselwort break die switch-An-
weisung beendet oder der switch-Block beendet ist.
● default: Zu dem zu default gehörenden Anweisungsblock wird verzweigt,
wenn die Überprüfung des switch-Ausdrucks mit den case-Marken keine Über-
einstimmung ergibt.

Ausführung: Auswertung der switch-Anweisung


● Die Konstanten bei den case-Marken werden in der Reihenfolge, in der sie im
Programmcode stehen, mit dem switch-Ausdruck verglichen.
● Wenn an einer Stelle Ausdruck und Konstante identisch sind, wird zu der zu-
gehörigen Anweisung verzweigt.
● Ergeben alle Vergleiche das Ergebnis false, wird, falls die default-Marke vor-
handen ist, zu den Anweisungen hinter default verzweigt.
● Da die Konstanten nur als Einsprungmarken dienen, wird die Ausführung
nach gefundener Übereinstimmung solange fortgesetzt, bis die switch-Anwei-
sung zu Ende ist. Darum wird (es sei denn, dieses Durchfallen wird explizit ge-
wünscht) jede zu einem case gehörende Anweisung mit dem Schlüsselwort
break beendet. Trifft der Compiler auf das break, wird die switch-Anweisung
sofort verlassen.
● Innerhalb einer switch-Anweisung dürfen keine zwei Konstanten den gleichen
Wert haben. Sollte dies doch der Fall sein, erzeugt der Compiler eine Fehler-
meldung.
● Zeichenkonstanten werden in switch-Anweisungen automatisch in ihren Inte-
ger-Wert umgewandelt.
● Innerhalb des switch-Blocks können keine Variablen definiert und initialisiert
werden.

Beispiele
#include <stdio.h>
int main(){
float zahl1, zahl2;
char Operator;

printf("Ein kleiner Taschenrechner:\n");


printf("Geben Sie ein: Zahl Operator Zahl <Return>\n");
scanf("%f %c %f", &zahl1, &Operator, &zahl2);

switch (Operator)
{
case '+':

136
Schleifen

printf("= %f", zahl1 + zahl2);


break;
case '-':
printf("= %f", zahl1 – zahl2);
break;
case 'X':
case 'x':
case '*':
printf("= %f", zahl1 * zahl2);
break;
case ':':
case '/':
printf("= %f", zahl1 / zahl2);
break;
default:
printf("Operator nicht bekannt");
} // end of switch

printf("\n\n");
return 0;
}

Verweise
Siehe if-Anweisung

Schleifen
for, while

Beschreibung
Schleifen werden eingesetzt, wenn ein Anweisungsblock mehrere Male hintereinander ausge-
führt werden soll.
Schleifen bestehen aus
● einer Abbruchbedingung, die festlegt, wann die Ausführung der Schleife zu be-
enden ist, und
● einem in geschweifte Klammern eingefaßten Anweisungsblock.

Anwendung
In C/C++ gibt es while, for und do-while-Schleifen. Prinzipiell aber läßt sich jede
Schleife als while-Schleife formulieren. Unabhängig von der verwendeten Schleife
kann diese auf mehrere Weisen verlassen werden:
● Abbruchbedingung der Schleife wird erfüllt.
● Abbruch durch break , return oder exit().
● Sprung aus Schleife heraus durch goto oder longjmp().

137
Sprachkonzepte und Syntax

Warnung
Es ist Aufgabe des Programmierers sicherzustellen, daß eine Schleife auch wieder
verlassen wird, da das Programm sonst in einer Endlosschleife verharren kann.

Die for-Schleife
Beschreibung
Mit dem Schlüsselwort for wird eine Schleife eingeleitet, die durch einen dreiteiligen Schlei-
fenkopf kontrolliert wird. Dieser Schleifenkopf steht in runden Klammern und enthält die drei
Elemente Initialisierung, Bedingung und Veränderung, die durch Semikolon voneinander
getrennt werden.

Anwendung
Die for-Schleife wird immer dann eingesetzt, wenn die gewünschten Wiederho-
lungen des Anweisungsblocks abzählbar sind (im Gegensatz zur while-Schleife, die
auch eingesetzt werden kann, wenn die Anzahl der Wiederholungen nicht berech-
net werden kann). In der Praxis sieht dies meist so aus, daß man eine eigene
Variable definiert (die sogenannte Schleifenvariable), diese zu Beginn der Schleife
initialisiert und dann bei jedem Durchgang der Schleife um einen bestimmten
Betrag erhöht oder erniedrigt, bis sie einen bestimmten Wert übersteigt oder unter-
schreitet, und dadurch die Schleifenbedingung nicht mehr erfüllt ist. Die Syntax der
for-Schleife ist speziell auf diese Formulierung einer Schleife abgestimmt.

Syntax
for (Initialisierung; Bedingung; Reinitialisierung)
Anweisung;
● Initialisierung: Die im Initialisierungsteil stehenden Anweisungen werden
ausgeführt, bevor die Schleife beginnt. Dort werden üblicherweise die Schlei-
fen- oder Zählvariablen initialisiert. Es ist auch möglich, in dieser Anweisung
mehrere Variablen zu initialisieren. Die Zuweisungen werden dann durch
Kommata voneinander getrennt.
● Bedingung: Der Bedingungsteil enthält einen Ausdruck, der wahr sein muß,
damit der zur for-Schleife gehörende Anweisungsteil ausgeführt wird.
● Reinitialisierung: Die hier stehenden Anweisungen werden nach jedem Durch-
lauf des zu for gehörenden Anweisungsblocks abgearbeitet. Hier wird meist
die Zählervariable erhöht oder vermindert. Es kann dort jedoch auch jede an-
dere Anweisung aufgenommen werden. Stehen hier mehrere Anweisungen,
werden sie durch Kommata getrennt.

138
Die while-Schleife

● Anweisung: Der Anweisungsteil kann aus einer einzelnen Anweisung oder aus
einem Anweisungsblock bestehen. Eine einzelne Anweisung muß immer mit
einem Semikolon (dem Anweisungsbegrenzer) beendet werden. Wenn ein An-
weisungsblock ausgeführt werden soll, muß dieser in geschweifte Klammern
eingeschlossen werden.

Warnung
Eine Sonderform der for-Schleife stellt die Endlosschleife dar.
for(;;)
Sie erhält man, wenn alle drei Elemente der Definition der for-Schleife wegfallen,
und wenn nur die Semikolons, die die Elemente trennen, stehenbleiben. Endlos-
schleifen dieser Art können, da keine Abbruchbedingung vorhanden ist, nur mit
break, return oder goto verlassen werden.

Beispiele
#include <stdio.h>
int main() {
int zaehler;
for(zaehler = 0; zaehler < 10; zaehler++)
printf("Der Wert von zaehler beträgt: %d\n", zaehler);
return 0;
}

Verweise
Siehe Abbruchbefehle
Siehe while-Schleife

Die while-Schleife
Beschreibung
Die while-Schleife ist die allgemeinste Form der Schleife, mit der man einen Anweisungsblock
in Abhängigkeit von einer Schleifenbedingung mehrfach ausführen lassen kann.

Anwendung
Die while-Schleife gleicht in der Syntax der if-Bedingung, nur daß die Bedingung
nicht kontrolliert, ob der Anweisungsblock überhaupt ausgeführt wird, sondern
wie oft er ausgeführt wird.

139
Sprachkonzepte und Syntax

Ansonsten verfügen aber auch while-Schleifen – genau wir for-Schleifen – häufig


über Schleifenvariablen, die in die Schleifenbedingung eingehen und innerhalb des
Anweisungsblocks der Schleife verändert werden – nur, daß Initialisierung und
Veränderung der Schleifenvariable nicht wie bei der for-Schleife in den Schleifen-
kopf integriert werden können.
Die while-Schleife wird aber auch häufig eingesetzt, wenn der Schleifenabbruch
nicht von einer Schleifenvariablen, sondern von anderen Ereignissen (z. B. Benutzer-
eingaben) abhängt. Die Schleife wird dann üblicherweise mittels einer break-Anwei-
sung verlassen.

Syntax
while (Bedingung)
Anweisung;
● Bedingung: Die Bedingung, die ausgewertet wird, muß einen Booleschen Wert
ergeben. Hier kann beispielsweise eine Ganzzahl, eine arithmetische Operati-
on, ein Vergleich oder der Aufruf einer Funktion mit entsprechendem Rückga-
betyp stehen.
● Anweisung: Das Element Anweisung kann eine einzelne Anweisung sein oder
aus einem Anweisungsblock bestehen. Eine einzelne Anweisung muß immer
mit einem Semikolon (dem Anweisungsbegrenzer) beendet werden. Wenn ein
Anweisungsblock ausgeführt werden soll, muß dieser in geschweifte Klam-
mern eingeschlossen werden.

Beispiele
Die while-Schleife ist die allgemeinste Form der Schleife. So kann man beispiels-
weise die folgende for-Schleife
for (i=1; i <= 5; i++)
printf("%d ", i);

auch als while-Schleife formulieren:


i = 1;
while (i <= 5) {
printf("%d ", i);
i++;
}

Ausführung: Auswertung der while-Schleife


● Die Bedingung der while-Schleife wird getestet, bevor die zur Schleife gehören-
de Anweisung ausgeführt wird.
● Die Schleife endet, wenn die Bedingung nicht mehr den Wert true ergibt.

140
Die do-while-Schleife

● Liefert die Auswertung der Bedingung der while-Schleife bereits beim Eintritt
den Wert false, werden die zur Schleife gehörenden Anweisungen nie ausge-
führt.

Verweise
Siehe Abbruchbefehle
Siehe for-Schleife

Die do-while-Schleife
Beschreibung
Neben der while-Schleife gibt es noch das Konstrukt der do-while-Schleife, die mit dem
Schlüsselwort do eingeleitet wird und bei der die Schleifenbedingung am Ende des Anwei-
sungsblocks steht.

Anwendung
Der wichtigste Unterschied zur while-Schleife besteht darin, daß der Anweisungsteil
der do-Schleife mindestens einmal ausgeführt wird, da die Bewertung des Aus-
drucks, der die Bedingung zum Abbruch oder der Schleife enthält, immer nach dem
Durchlaufen des Anweisungsteils stattfindet.

Syntax
do
Anweisung;
while (Bedingung);

Beispiele
#include <stdio.h>
int main() {
int zahl = 99;
do {
printf("Geben Sie eine Zahl ein. ");
printf("99 um Programm zu beenden.\n");
scanf("%d", &zahl);
printf("Die eingelesene Zahl ");
printf("war: %d\n", zahl);
} while (zahl != 99);
return 0;
}

141
Sprachkonzepte und Syntax

Verweise
Siehe for-Schleife
Siehe while-Schleife

Abbruchbefehle für Schleifen


Beschreibung
Mit einer Reihe von Befehlen kann man Schleifen bei Bedarf vorzeitig abbrechen.

Anwendung
Grundsätzlich kontrolliert die Schleifenbedingung, wie oft der Anweisungsblock
einer Schleife auszuführen ist. Darüber hinaus gibt es aber auch die Möglichkeit,
einzelne Schleifendurchgänge gezielt zu überspringen oder eine Schleife vorzeitig
abzubrechen.

continue Mit der continue Anweisung wird zum Ende des Schleifenblocks
gesprungen. Die Ausführung der nach continue stehenden Anweisungen
unterbleibt und der nächste Schleifendurchgang beginnt.
break Das Schlüsselwort break wurde bereits zusammen mit der switch-Anwei-
sung vorgestellt. Neben der Beendigung der switch-Verzweigung können
Sie auch die Ausführung einer Schleife mittels break beenden. Im Gegen-
satz zu continue wird dabei nicht nur der aktuelle Schleifendurchgang
abgebrochen, sondern die Schleife wird ganz verlassen.

Neben continue und break gibt es noch weitere Schlüsselwörter und Funktionen, die
man zum Verlassen einer Schleife – oder allgemein eines Anweisungsblocks – ver-
wenden kann.

return Mit dem Schlüsselwort return kann die Ausführung einer Funktion
unterbrochen und sofort an der Stelle fortgesetzt werden, an der die
Funktion aufgerufen wurde.
exit() Mit der Funktion exit() kann ein Programm an beliebiger Stelle abge-
brochen werden. Dies wird meist benutzt, wenn ein schwerwiegender
Fehler aufgetreten ist, der den weiteren Programmablauf sinnlos oder
unmöglich macht.
throw Löst eine Exception aus und springt zum nächsten passenden Exception-
Handler (nur für die Fehlerbehandlung).
goto Mit goto kann zu einem beliebigen anderen Punkt innerhalb der aktuellen
Funktion verzweigt werden, der durch eine Sprungmarke gekennzeichnet
wurde. Die Sprungmarke erhält einen Namen und wird, wie die Marken
der switch-Anweisung, mit einem Doppelpunkt abgeschlossen.
longjmp() Setzt das Programm in einen Zustand zurück, der zuvor durch einen
Aufruf von setjmp() abgespeichert wurde.

142
Funktionen

Beispiele
Überspringen einzelner Iterationen mit continue:
#include <stdio.h>
int main() {
int zahl;
do {
printf("Geben Sie eine Zahl ein. ");
printf("99 um Programm zu beenden.\n");
scanf("%d", &zahl);
if (zahl < 0)
continue;
printf("Die eingelesene Zahl ");
printf("war: %d\n", zahl);
} while (zahl != 99);
return 0;
}
Vorzeitiges Abbrechen einer Schleife mit break:
int main() {
int zahl;
for (zahl = 3; zahl < 15; zahl++) {
if (zahl == 8)
break;
printf("zahl hat folgenden Wert: %d\n", zahl);
}
return 0;
}

Verweise
Siehe for-Schleife
Siehe while-Schleife

Funktionen

Funktionen
Beschreibung
C-Programme bestehen aus einer beliebigen Anzahl von Funktionen, deren Namen innerhalb
der Konventionen von C (siehe Grundlagenteil) frei gewählt werden dürfen.

143
Sprachkonzepte und Syntax

Anwendung
Sinn einer Funktionsdefinition ist es, einen Anweisungsblock, der eine bestimmte
Aufgabe erledigt (beispielsweise die Ausgabe auf Konsole, die Berechnung des Sinus,
etc.), mit einem Namen zu verbinden. Wird dann irgendwo im Programm die Funk-
tion über ihren Namen aufgerufen, wird die Programmausführung mit der ersten
Anweisung aus dem Anweisungsteil der Funktion fortgesetzt. Nach Abarbeitung der
Funktion springt die Programmausführung in die Zeile des Funktionsaufrufs zurück.
Die Aufteilung des Quelltextes in Funktionen ermöglicht es, redundanten Code zu
vermeiden, häufig benötigte Funktionen zu sogenannten Bibliotheken zusammenzu-
fassen und die Programme modularer und damit wartungsfreundlicher zu gestalten.
Zum Datenaustausch mit der aufrufenden Funktion kann eine Funktion eine belie-
bige Anzahl Parameter und einen Rückgabwert definieren.
Funktionen können an beliebiger Stelle im Quelltext definiert werden (nicht aber
innerhalb anderer Funktionen). Bevor man eine Funktion aufrufen kann, muß sie
aber dem Compiler bekannt sein. Dies erreicht man, indem man die Funktionsdefi-
nition an den Anfang der Quelltextdatei setzt oder indem man die Funktion an
beliebiger Stelle definiert und lediglich eine Vorwärtsdeklaration der Funktion an
den Programmanfang setzt. Letzteres System liegt auch der Verwendung von Hea-
der-Dateien für Bibliotheken zugrunde.

Beispiele
#include <stdio.h> /* Deklarationen für printf, scanf, fflush */
double fakul(int zahl); /* Vorwärtsdeklaration zu fakul() */

int main() {
int zahl;
double fakultaet;

printf("Geben Sie die Zahl ein: ");


scanf("%d",&zahl);
fflush(stdin);
fakultaet = fakul(zahl);
printf("\nDie Fakultaet von %d ist %lf\n", zahl, fakultaet);
return 0;
}

double fakul(int zahl) {


int loop;
double fakultaet = 1;

for(loop=zahl; loop>=1; loop--)


{
fakultaet *= loop;
}

return fakultaet;
}

144
Funktionsdeklaration und -definition

Funktionsdeklaration und -definition


Beschreibung
Mit der Funktionsdeklaration werden der Rückgabetyp, der Name und die Parameter festgelegt.
Eine Funktionsdefinition enthält zusätzlich den Funktionskörper, der in geschweiften Klam-
mern die Anweisungen umfaßt.

Anwendung
Bei der Funktionsdefinition wird ein Anweisungsblock mit einem Funktionsnamen
verbunden, so daß beim Aufruf des Funktionsnamens im Programmcode der
Anweisungsblock der Funktion ausgeführt wird. Zudem wird durch Angabe der
Parameter und des Rückgabetyps der Funktion festgelegt, wie die Funktion Daten
beim Aufruf übernimmt und bei ihrer Rückkehr zurückliefert.

Syntax
Typ func_name (PARAMETERLISTE)
{
FUNKTIONSKöRPER
}
● Typ: Mit der Typangabe wird festgelegt, welchen Rückgabewert die Funktion
hat. Arrays und Funktionstypen sind als Rückgabetyp nicht zulässig, wohl
aber Zeiger auf diese Objekte.
● func_name: Der Name der Funktion. Dieser Name muß in C, nicht aber in
C++, eindeutig sein (siehe Überladung).
● PARAMETERLISTE: In einer Definition stehen hier durch Kommata getrennt
die einzelnen Parameter mit ihren Typen. In einer Deklaration reicht die Anga-
be der Parametertypen, die der Compiler zur Typenüberprüfung und zur Auf-
lösung überladener Namen braucht (C++). In C++ können Vorgabeargumente
an die Parameter vergeben werden.
● FUNKTIONSKÖRPER: Der Funktionskörper ist ein Anweisungsblock, der in
geschweifte Klammern eingeschlossen wird und bei Aufruf der Funktion aus-
geführt wird.

145
Sprachkonzepte und Syntax

Warnung
● Funktionen haben standardmäßig die Speicherklasse extern. Darüber hinaus
kann man Funktionen auch als static deklarieren.
● Die standardmäßige extern-Deklaration von Funktionen bewirkt, daß die
Funktionen externe Bindung haben (es sei denn, es gibt im Quelltext eine vor-
angehende static-Deklaration der Funktion). Alle extern-Deklarationen einer
bestimmten Funktion beziehen sich daher über Dateigrenzen hinweg auf ein
und dieselbe Definition der Funktion. Auf diese Weise ist es möglich, über
eine Vorwärtsdeklaration in einer Quelltextdatei eine Verbindung zu einer
Funktion herzustellen, die in einer anderen Quelltextdatei oder einer Biblio-
thek definiert ist .
● Deklariert man eine Funktion als static, hat die Funktion interne Bindung,
d. h., der Name der Funktion ist nur innerhalb der eigenen Quelltextdatei be-
kannt. Auf diese Weise kann man in den verschiedenen Quelltextdateien eines
Programmes gleichnamige Funktionen definieren (aber natürlich nur eine pro
Datei), ohne daß es zu Linker-Fehlern wegen Mehrfachdefinitionen kommt.
● Funktionen, die keinen Wert zurückgeben sollen, erhalten die Typangabe void.
● Funktionen, für die kein Rückgabetyp angegeben wurde, bekommen in C au-
tomatisch den Rückgabetyp int zugewiesen (in C++ ist dies ein Fehler).
● Werden in einer Funktionsdeklaration, die nicht Teil einer Definition ist, keine
Parameter spezifiziert, wird dies unter C als Funktion mit beliebig vielen Para-
metern interpretiert, in C++ als Funktion ohne Parameter. Durch Angabe des
Schlüsselworts void statt einer Parameterliste kann in C eindeutig eine Funkti-
on ohne Parameter deklariert werden.
● Neben dem überflüssigen Schlüsselwort auto ist register die einzige Speicher-
klassenangabe, die für Parameter vergeben werden kann. Dadurch wird beim
Aufruf der Funktion, sofern möglich, das so deklarierte Argument in ein Pro-
zessorregister geladen.
● Die Angabe ... am Ende der Parameterliste bedeutet, daß noch beliebig viele
Argumente übergeben werden können.
● Funktionsname und die Parameterliste bilden zusammengenommen die Signa-
tur der Funktion.
● Innerhalb des Funktionskörpers können eigene Variablen definiert werden,
die, wenn nicht anders angegeben, die Speicherklasse auto besitzen und loka-
len Gültigkeitsbereich haben. Diese lokalen Variablen werden beim Aufruf der
Funktion auf dem Stack erzeugt und beim Verlassen der Funktion automatisch
wieder entfernt.
● Soll der Wert einer lokalen Variablen auch nach dem Verlassen der Funktion
erhalten bleiben, kann die Speicherklasse static benutzt werden. Meist wird
dies benutzt, um die Werte lokaler Variablen von Funktionsaufruf zu Funkti-
onsaufruf weiterzureichen.

146
Die Funktion main()

● In C++ kann man Funktionen als inline deklarieren, um den Compiler anzu-
weisen, wenn möglich, die Funktionsaufrufe nicht durch einen Sprung in den
Anweisungsteil der Funktion, sondern direkt durch Anweisungen, die mit der
Ausführung der Funktion identisch sind, zu ersetzen. Dies ist allerdings nur
eine Empfehlung an den Compiler.
● In C++ kann man mit Hilfe des Schlüsselwortes throw bei der Funktionsdekla-
ration eine Liste der Exceptions angeben, die in der Funktion ausgelöst wer-
den dürfen. Treten in der Funktion Exceptions anderer Typen auf, wird eine
unexpected-Exceptions ausgelöst.

Beispiele
int main();
int func1(char* s, int n);
void func2();
Vorgabeargumente in C++:
int func3(double par, char* s = "Vorgabe", int n = 2);
Überladene Funktionen in C++:
void func(int n);
int func(int n, int m);
int func(float f);

Warnung
Die alte auf Kernighan/Ritchie zurückgehende Form der Funktionsdefinition, bei
der die Parameter unter dem Funktionsnamen definiert wurden, ist in C obsolet
und in C++ nicht mehr möglich.
// func_name(a,b)
// int a, double b;
// { ...

Verweise
Siehe Klassen, Methoden

Die Funktion main()


Beschreibung
Der ANSI-Standard schreibt vor, daß eine der Funktionen in einem C/C++-Programm den
Namen main() tragen muß. Diese Funktion ist die Eintrittsfunktion eines Programms, der nach
dem Start des Programms automatisch die Kontrolle übergeben wird. Zusätzlich soll sie die
Möglichkeit bieten, Kommandozeilenargumente zu übernehmen.

147
Sprachkonzepte und Syntax

Anwendung
Der ANSI-Standard sieht folgende Definitionen vor:
int main() { }
int main(int argc, char *argv[]) { }
Die meisten Compiler erlauben aber auch void als Rückgabewert:
void main() { }
void main(int argc, char *argv[]) { }

main() ohne Argumente main()


Programme, die keine Argumente aus dem Programmaufruf übernehmen, definie-
ren main() ohne Parameter.
int main () { }
void main ( ) { }

main() und ihre Parameter main(int, char**)


Der ANSI-Standard sieht auch vor, daß der Funktion main() optional zwei Argu-
mente übergeben werden können. Die Namen für diese Argumente sind frei wähl-
bar, jedoch haben sich die Namen argc und argv eingebürgert.
void main(int argc, char *argv[]) { }
● argc: (Abkürzung für »argument count«) ist der übliche Name für das erste
Argument der main()-Funktion. Der Datentyp von argc ist int. Der Wert von
argc entspricht der Anzahl der Zeichenketten in dem Array, auf das argv zeigt.
Per Definition kann argc nie einen negativen Wert annehmen.
● argv: (Abkürzung für »argument vector«) ist der übliche Name für das zweite
Argument der main()-Funktion. argv zeigt auf ein Array mit Zeigern vom Typ
char. Die Zeichenketten werden vom Lademodul des Systems an das Pro-
gramm übergeben.
Die Anzahl der Parameter wird durch das Argument argc festgelegt. Per Definition
zeigt argv[0] (also der erste Zeiger) immer auf den Namen des Programms, wäh-
rend argv[argc] ein NULL-Zeiger ist.
Die einzelnen Parameter befinden sich in argv[1] bis argv[argc-1].

Beispiele
#include <stdio.h>
#include <stdlib.h>

int main( int argc, char *argv[]) {


int i;
printf( "\nBefehlszeilen-Argumente:\n" );
for( i = 0; i < argc; i++ )
printf( " argv[%d] %s\n", i, argv[i] );

148
Datenaustausch zwischen Funktionen

return( EXIT_SUCCESS );
}
Nachstehend sehen Sie die Ausgabe des Programms, wenn der Name des Pro-
gramms [Link] ist, und es mit folgender Befehlszeile aufgerufen wurde:
C:\CC>main eins zwei drei
Befehlszeilen-Argumente:
argv[0] C:\CC\[Link]
argv[1] eins
argv[2] zwei
argv[3] drei

Verweise
Siehe Grundlagenteil, Aufbau eines C/C++-Programms

Datenaustausch zwischen Funktionen


Beschreibung
Prinzipiell besteht ein C-Quelltext nur aus Deklarationen und Definitionen. Anweisungen fin-
den sich nur in Funktionsdefinitionen. Damit Funktionen zusammenarbeiten können, müssen
sie Informationen, sprich Daten, austauschen. Dazu gibt es in C verschiedene Konzepte.

Anwendung
Parameter Parameter sind spezielle Variablen einer Funktion, denen beim
Aufruf der Funktion Werte zugewiesen werden. Werden als
Parameter Zeiger definiert, kann die Funktion auf diesem Weg
auch Daten zurückliefern.
Rückgabewert Ein einzelner Wert, den die Funktion an den Aufrufer zurück-
gibt.
Globale Variablen Eine weitere Möglichkeit, Daten zwischen Funktionen auszu-
tauschen, läuft über die globalen Variablen. Dieser Weg ist
sehr einfach, hat aber den Nachteil, daß die Unabhängigkeit
und Abgeschlossenheit der Funktion dadurch beeinträchtigt
wird.
Statische Variablen Sollte es erforderlich sein, daß eine lokale Variable nicht nach
dem Verlassen der Funktion gelöscht werden darf, damit ihr
Wert beim nächsten Aufruf der Funktion noch erhalten ist,
wird die Variable als static deklariert.

149
Sprachkonzepte und Syntax

Verweise
Siehe nachfolgende Abschnitte

Der Rückgabewert
Beschreibung
Funktionen können das Ergebnis ihrer Berechnung über den Rückgabewert zurückliefern. Dazu
wird der Typ des Rückgabewerts im Funktionskopf spezifiert. Mittels der Anweisung
return (ergebnis);
wird der Wert dann an die aufrufende Funktion zurückgeliefert.

Anwendung
Es gibt zwei Möglichkeiten, das Konzept des Rückgabewertes sinnvoll zu nutzen:
● Das Ergebnis der Funktion wird einer Variablen der aufrufenden Funktion zu-
gewiesen.
● Die Funktion meldet zurück, ob sie ihre Aufgabe erfolgreich gelöst hat, oder
ob in der Funktion ein Fehler aufgetreten ist.

Warnung
Funktionen, die keinen Wert zurückliefern, erhalten den Rückgabetyp void. Eine
solche Funktion kann return nur ohne Wert aufrufen: return; .

Verweise
Siehe Parameter
Siehe Kategorie Programmsteuerung, Abbruchbefehle für Schleifen

Parameter
Beschreibung
Die Parameter dienen dazu, Werte von der aufrufenden Funktion an die aufgerufene Funktion
zu übergeben. Parameter sind stets lokale Variablen, deren Gültigkeitsbereich der äußerste
Block der Funktion ist. Zur Übergabe von Daten an Parameter benutzt C standardmäßig ein Ver-
fahren, das man »call by value« nennt.

150
Parameter

Wert kopieren call by value


Dies bedeutet, daß beim Funktionsaufruf der Wert des übergebenen Arguments in
die lokale Variable kopiert wird.
Dieses Konzept stellt sicher, daß als Argument übergebene Variablen nicht von den
aufgerufenen Funktionen verändert werden können:

Beispiele
#include <stdio.h>
void change(int param) {
printf("\tParam nach Funktionsaufruf: %d\n",param);
param = param*param;
printf("\tParam nach Berechnung: %d\n",param);
}

int main() {
int var = 10;
printf("var vor Funktionsaufruf: %d\n",var);

change(var);
printf("var nach Funktionsaufruf: %d\n",var);
return 0;
}
liefert folgende Ausgabe:
var vor Funktionsaufruf: 10
Param nach Funktionsaufruf: 10
Param nach Berechnung: 100
var nach Funktionsaufruf: 10

Adresse kopieren call by reference


Das Pendant heißt »call by reference«. Dabei wird nicht der Wert einer Argument-
variablen übergeben, sondern ihre Adresse! Da die Funktion in diesem Fall statt
einer Kopie eine Referenz auf das Aufrufargument erhält, kann sie dieses verän-
dern. Referenzparameter sind daher neben dem Rückgabewert ein weiteres Mittel,
um Daten von der aufgerufenen Funktion an die aufrufende Funktion zurückzu-
geben.
Für »call by reference«-Übergaben gibt es folgende Möglichkeiten:

Parameter Argument
Zeiger:
Typ * ptr (Zeiger vom Typ typ*)
typ * &var (Adresse einer Variablen vom Typ typ)
Referenz, nur C++:

151
Sprachkonzepte und Syntax

Parameter Argument
typ & var (Variable vom Typ typ)

Beispiele
#include <stdio.h>

void change1(int param) {


param = param*param;
}

void change2(int *param) {


*param = *param * *param;
}

void change3(int &param) {


param = param*param;
}

int main() {
int var = 10;
change1(var); printf("var : %d\n",var);
change2(&var); printf("var : %d\n",var);
change3(var); printf("var : %d\n",var);

return 0;
}
liefert folgende Ausgabe:
var : 10
var : 100
var : 10000

Warnung
Gelegentlich werden Zeiger übergeben, ohne daß eine Änderung des übergebenen
Wertes erwünscht wäre. Dies kann zum Beispiel bei der Übergabe von Arrays der
Fall sein, die immer als Zeiger übergeben werden, oder wenn Zeiger auf größere
Datenstrukturen übergeben werden, um das Kopieren zu sparen. In solchen Fällen
kann durch den Spezifizierer const in der Parameterdeklaration die entsprechende
Variable vor dem Überschreiben geschützt werden.

Tip
In C++ werden statt Zeigern häufig Referenzen zur effizienten Übergabe von Argu-
menten an Funktionen benutzt.

Verweise
Siehe Rückgabewert

152
Funktionsargumente und Vorgabe

Funktionsargumente und Vorgabe


Beschreibung
In C++ können in der Funktionsdeklaration Vorgabeargumente vergeben werden. Parametern,
für die Vorgabeargumente deklariert wurden, brauchen beim Funktionsaufruf keine Argumente
mehr übergeben zu werden.

Anwendung
Auf diese Weise kann der Aufruf für häufig übergebene Argumente vereinfacht
werden.

Warnung
● Auf einen Parameter mit Vorgabeargument dürfen keine Parameter ohne Vor-
gabeargumente mehr folgen.
● Bei einer Redeklaration dürfen weitere Vorgabeargumente angegeben werden,
es dürfen jedoch keine bereits deklarierten Vorgabeargumente redeklariert
werden.
● Als Vorgabeargumente können auch Ausdrücke oder Variablen deklariert
werden. Es dürfen jedoch keine lokalen Variablen verwendet werden.
● Die Reihenfolge, in der die Funktionsargumente ausgewertet werden, ist nicht
festgelegt und kann somit von Compiler zu Compiler verschieden sein.

Beispiele
int func1(int n, int m = 3);
void func2(char *s = "Vorgabe");
char* func3(int x, int y=4);
char* func3(int x = 2, int y); // gueltige Redeklaration
int func4(int a = 0, int b); // Fehler

153
Sprachkonzepte und Syntax

Funktionen und der Stack


Beschreibung
Der Stack ist ein dynamisch wachsender und schrumpfender Speicherbereich, der vom Compiler
verwaltet wird. Hier legt der Compiler alle Informationen ab, die er für die Protokollierung und
Verwaltung der Funktionsaufrufe benötigt.
Immer wenn Sie eine Funktion aufrufen, wird der Stack um einen neuen Datenblock erweitert.
In diesem Datenblock werden die Parameter der Funktion, die lokalen Variablen der Funktion
und einige interne Informationen (von denen die Rücksprungadresse zum Code der aufrufen-
den Funktion die wichtigste ist) abgelegt. Diesen Datenblock nennt man auch den Stack-Frame
oder Stackrahmen der Funktion.

Stack-Aktionen
● Solange eine Funktion abgearbeitet wird, bleibt ihr Stack-Frame auf dem
Stack liegen.
● Werden aus einer Funktion heraus weitere Funktionen aufgerufen, werden
deren Stack-Frames auf den Stack-Frame der jeweils zuvor aufgerufenen Funk-
tion draufgepackt.

154
Funktionen und der Stack

● Wird eine Funktion beendet, wird ihr Stack-Frame vom Stack entfernt.
● Der Stack ist also immer das genaue Abbild der zur Zeit noch in Ausführung
befindlichen Funktionen. Die Stapelreihenfolge der Funktionen zeigt an, wel-
che Funktion von welcher anderen Funktion aufgerufen wurde.

Stack-Aufbau
Für einen von oben nach unten wachsenden Stack gilt:
● Die unterste Funktion ist die aktuelle Funktion, deren Anweisungen gerade
abgearbeitet werden.
● Die darüberliegende Funktion hat die unterste Funktion aufgerufen und war-
tet nun, daß die aufgerufene Funktion beendet wird.
● Die oberste Funktion ist die Eintrittsfunktion main().
● Die einzelnen Stack-Frames von oben nach unten gelesen zeigen an, über wel-
che Funktionen die aktuelle Funktion aufgerufen wurde.
Der genaue Aufbau der Stack-Frames hängt von dem Rechner ab, für den das Pro-
gramm kompiliert wurde (die Abbildung ist also nur als eine Art allgemeines Modell
zu verstehen). Sie können der Stack-Verwaltung Ihres Rechners aber ein wenig nach-
spüren, indem Sie sich der Debug-Tools Ihres Compilers bedienen (Stack-Anzeige)
oder sich die Adressen der Parameter und lokalen Variablen ausgeben lassen.

Beispiele
#include <stdio.h>
#include <stdlib.h>

func(int par1, int par2, int par3)


{
int lokal1, lokal2, lokal3;
printf("%d. Aufruf von func\n",par1);
printf("\t Adresse von par3 = %p\n",&par3);
printf("\t Adresse von par2 = %p\n",&par2);
printf("\t Adresse von par1 = %p\n",&par1);
printf("\t Adresse von lokal1 = %p\n",&lokal1);
printf("\t Adresse von lokal2 = %p\n",&lokal2);
printf("\t Adresse von lokal3 = %p\n",&lokal3);
if(par1<2)
func(++par1,0,0);
}

int main()
{
func(1,0,0);
return 0;
}

155
Sprachkonzepte und Syntax

Ausgabe
1. Aufruf von func
Adresse von par3 = 0065FE00
Adresse von par2 = 0065FDFC
Adresse von par1 = 0065FDF8
Adresse von lokal1 = 0065FDEC
Adresse von lokal2 = 0065FDE8
Adresse von lokal3 = 0065FDE4
2. Aufruf von func
Adresse von par3 = 0065FDE0
Adresse von par2 = 0065FDDC
Adresse von par1 = 0065FDD8
Adresse von lokal1 = 0065FDCC
Adresse von lokal2 = 0065FDC8
Adresse von lokal3 = 0065FDC4

Erläuterung
Die obige Ausgabe ist das Abbild einer sich selbst aufrufenden Funktion.
Die Adressen der Parameter werden in umgekehrter Reihenfolge ausgegeben, weil
der Compiler den letzten Parameter zuerst auf dem Stack ablegt.
Wie man der Ausgabe entnehmen kann, wird der Stack im Speicher von oben nach
unten aufgebaut, d. h., der Stack-Frame der Funktion, die als letztes aufgerufen
wird, und der damit den obersten Stack-Frame bildet, liegt im Speicher an der nied-
rigsten Speicheradresse.
Der Stack-Frame für den ersten Aufruf von func() beginnt an der Adresse
0065FE00, der Stack-Frame für den zweiten Aufruf an der Adresse 0065FDE0. Im
Stackrahmen werden zuerst die drei int-Parameter abgelegt. Jeder int-Parameter
belegt 4 Byte (wie für 32-Bit-Systeme üblich). Dann folgt ein Leerraum, in dem
Daten abgelegt werden, auf die wir keinen direkten Zugriff haben (vermutlich die
Rücksprungadresse und ein Zeiger auf den Beginn des vorangehenden Stack-Fra-
mes). Danach folgen die lokalen Variablen, die gemäß ihrem Datentyp wiederum
jeweils 4 Byte belegen.

Warnung
● Wenn in C/C++ eine Funktion aufgerufen wird, wird für die Funktion Spei-
cherplatz reserviert. Die Einrichtung und Verwaltung des Speicherbereichs der
Funktion kostet auch Laufzeit. Diesen Zeitverlust bezeichnet man als Function
Overhead.
● In dem für die Funktion bereitgestellten Speicherbereich liegen die Speicherzel-
len der Funktionsparameter, der lokalen Variablen und der Rücksprungadres-
se, die sicherstellt, daß nach Abarbeitung der Funktion wieder an die richtige
Stelle im Programm zurückgesprungen wird. Bei Beenden der Funktion gibt

156
Funktionen mit beliebig vielen Argumenten

C/C++ diesen Speicherbereich wieder frei, es entsteht also kein Speicherver-


lust. Es sei denn, Sie verwenden rekursive Funktionen. Ist die Rekursionstiefe
sehr groß oder die lokalen Variablen der rekursiven Funktion sehr speicher-
aufwendig, kann es passieren, daß während der Rekursion der Speicher voll-
ständig belegt wird, da für jeden Funktionsaufruf Speicherplatz reserviert
werden muß. Das Programm stürzt dann mit einer entsprechenden Fehlermel-
dung ab. Dies passiert zwangsläufig, wenn ihre Rekursion keine Abbruchbe-
dingung erreicht.

Verweise
Siehe Kategorie Variablen und Datentypen, Gültigkeitsbereiche

Funktionen mit beliebig vielen Argumenten


func(typ param, ...)

Beschreibung
C/C++ erlaubt auch die Definition von Funktionen mit unbekannter Parameterzahl. Das kommt
nicht gänzlich überraschend, denn schließlich erlauben auch einige gängige Bibliotheksfunk-
tionen eine variable Anzahl von Argumenten: printf() und scanf().

Anwendung
Die Implementierung von Funktionen mit beliebig vielen Argumenten beruht auf
zwei Elementen:
double mittel(int anzahl, ...)
● Der Ellipse. Die Ellipse ... in der Parameterliste zeigt an, daß bei Aufruf noch
eine beliebige Zahl von Argumenten folgen kann. Die Ellipse muß am Ende
der Parameterdefinition stehen, und ihr muß ein ordentlicher Parameter vor-
ausgehen, an dem man innerhalb der Funktion ablesen kann, wie viele Para-
meter folgen.
● Die va_Makros aus <stdarg.h>. Diese werden benötigt, um die Argumente zu
übernehmen und auszuwerten.

Beispiele
double mittel(int anzahl, ...) {
double summe = 0;
va_list ap;
int loop;

157
Sprachkonzepte und Syntax

va_start(ap, anzahl);
for(loop=1;loop<= anzahl;loop++)
summe += va_arg(ap,int);
va_end(ap);
return summe/anzahl;
}

Inline-Funktionen (nur C++)


Beschreibung
Inline-Funktionen sind Funktionen deren Aufrufe im Quelltext der Compiler möglichst nicht
durch wirkliche Funktionsaufufe und das damit verbundene Anlegen eines Stack-Frames auf-
löst, sondern statt dessen den Anweisungsblock der Funktion so in den Quelltext einbaut, daß
dessen Ausführung wirkt, als wäre die Funktion aufgerufen worden.

Anwendung
Aufrufe von Funktionen bedingen eine zeitliche Verzögerung, den sogenannten
Function Overhead. Man kann dies vermeiden, indem man Makros statt Funktio-
nen einsetzt. Ein Makroaufruf wird vom Compiler beim Übersetzen durch die
Makrodefinition ersetzt. Makros bringen jedoch einige Probleme mit sich:
● Sie nehmen keine Typüberprüfung vor, und
● Ihre Formulierung ist fehleranfälliger als die Definition von Funktionen.
C++ bietet daher die Alternative, Funktionen als inline zu deklarieren, indem das
Schlüsselwort inline einfach an den Anfang des Funktionskopfes gestellt wird. Das
Schlüsselwort inline weist den Compiler an, ähnlich wie bei einem Makro, die
Funktionsaufrufe durch die Funktionskörper zu ersetzen. Der Nachteil gegenüber
dem Gebrauch von Makros liegt darin, daß die inline-Direktive vom Compiler nur
als Empfehlung angesehen wird, die er nicht beachten muß.

Warnung
● Allgemein ist zum Gebrauch von Makros und Inline-Funktionen zu sagen, daß
sie zwar die Laufzeit eines Programms beschleunigen, dafür aber den Code
aufblähen. Sie eignen sich daher vor allem für kleinere Funktionen, die nicht
allzu oft aufgerufen werden.
● Methoden von Klassen, die innerhalb der Klasse definiert werden, werden
vom Compiler automatisch als Inline-Funktionen behandelt.

158
Spezifizierer für Funktionen

● Die inline-Deklaration ist nur eine Empfehlung. Für umfangreichere oder


komplexere Funktionen übergeht der Compiler üblicherweise die inline-De-
klaration.
● inline-Funktionen müssen in jeder Übersetzungseinheit des Programms iden-
tisch definiert werden (siehe Praxisteil, Elemente modulübergreifend nutzen).

Verweise
Siehe Funktionen und der Stack

Spezifizierer für Funktionen


Beschreibung
Einsatzbereich und Arbeitsweise einer Funktion können durch eine Reihe von speziellen
Schlüsselwörtern, die der Funktionsdeklaration voran- oder nachgestellt werden, manipuliert
werden.

Spezifizierer für Funktionen


Funktionen können mit einer der Speicherklassenangaben extern oder static verse-
hen werden:

static Die Verwendung von static als Schlüsselwort vor der Typangabe einer
Funktion verengt deren Sichtbarkeit auf die Datei, in der sie definiert ist.
extern Die Verwendung von extern als Schlüsselwort vor der Typangabe einer
Funktion macht sie in allen Dateien sichtbar, die zu dem Programm gehören
(Funktionen sind per Voreinstellung extern).
- Fehlt die Angabe, hat eine Funktion standardmäßig die Speicherklasse
extern.

In C++, nicht in C, können Funktionen als inline deklariert werden.

inline Die inline-Deklaration ist eine Empfehlung an den Compiler, Funktionsauf-


rufe durch direkten, äquivalenten Code zu ersetzen.

159
Sprachkonzepte und Syntax

Spezielle Spezifizierer für Methoden


static static-Methoden sind klassenspezifisch, aber nicht instanzspezifisch.
const const-Methoden können nur mutable-Instanzvariablen der Klasse verän-
dern. Zudem können für const-Instanzen nur const-Methoden der Klasse
aufgerufen werden. (Einige Compiler geben bei Zuwiderhandlung allerdings
nur eine Warnung aus.) Das Schlüsselwort const wird hinter die Parameter-
liste gesetzt.
volatile volatile-Methoden. Für volatile-Instanzen können nur volatile-Metho-
den der Klasse aufgerufen werden. Das Schlüsselwort volatile wird hinter
die Parameterliste gesetzt.
virtual virtual-Methoden werden bei der Vererbung eingesetzt und schalten die
späte Bindung für eine Methode ein.

Methoden können nicht als extern deklariert werden. extern ist im Grunde ein
Bezug auf eine globale Deklaration, die üblicherweise in externen Bindung resul-
tiert. Dies ist für Methoden weder erlaubt noch sinnvoll.

Beispiele
extern int func1();
static int func2();
inline int func3();

class demo {
static int func4();
int func5() const;
int func6() volatile;
virtual int func7();
};

Verweise
Siehe Funktionsdeklaration und -definition
Siehe Inline-Funktionen
Siehe Kategorie Klassen, Methoden

Überladung
Beschreibung
C++ erlaubt die Definition mehrerer Funktionen (oder Operatoren) gleichen Namens, sofern die
Funktionen sich in Anzahl oder Typ der Parameter unterscheiden. Die Definition mehrerer
Funktionen gleichen Namens bezeichnet man als Überladung.

160
Überladung

Realisierung und Auflösung


Prinzipiell gilt für C++ ebenso wie für C, daß Objekte über einen eindeutigen Namen
adressiert werden können. C++ lockert dieses Dogma für den Programmierer etwas
auf, indem Funktionenbezeichner automatisch um codierte Informationen zu den
Parametern respektive Operanden erweitert werden. Auf diese Weise kann der Pro-
grammierer identische Bezeichner vergeben, während der Compiler mit eindeutigen
Namen arbeitet. Dies erklärt auch, warum beispielsweise Variablen oder Funktionen
ohne Parameter nicht überladen werden können.
Umgekehrt muß der Compiler in der Lage sein, beim Aufruf einer überladenen
Funktion anhand der übergebenen Argumente die aufzurufende Funktion festzu-
stellen. Man bezeichnet dies als die Auflösung einer Überladung.
Zuerst sucht der Compiler dabei nach einer überladenen Funktion, die exakt in den
Datentypen ihrer Parameter mit den Datentypen der Argumente aus dem Funkti-
onsaufruf übereinstimmt.

● Ein Typ T kann nicht von seiner Referenz T& unterschieden werden.
● Ein Typ T kann nicht von const T oder volatile T unterschieden werden, wohl
aber T* von const T*.
Findet der Compiler keine exakte Übereinstimmung, sucht er die bestmögliche
Übereinstimmung.
● Zuerst wendet der Compiler die arithmetischen Promotionen auf die Argu-
mente an.
● Dann versucht er es mit Standardkonvertierungen (double zu int, int zu double,
Abgeleitet* zu Basis*, etc.),
● Am Schluß berücksichtigt er noch benutzerdefinierte Konvertierungen für
Klassen.

Warnung
Überladene Funktionen müssen in einem gemeinsamen Gültigkeitsbereich liegen,
sonst findet keine Überladung, sondern die übliche Verdeckung statt.
Der Rückgabetyp spielt bei der Überladung keine Rolle – überladene Funktionen
können also nicht anhand des Rückgabetyps unterschieden werden.
Findet der Compiler für ein Set von Argumenten zwei oder mehr überladene Ver-
sionen, die alle gleich gut zu den Argumenten passen, gibt er eine Fehlermeldung
aus, daß er die Überladung nicht eindeutig auflösen kann.
void func(char) {};
void func(short) {};

void call(char c, int i, short s)

161
Sprachkonzepte und Syntax

{
func(c); // ruft func(char) auf
func(s); // ruft func(short) auf
func(i); // Fehler: ambiguity
}
Das Problem liegt hier darin, daß es keine überladene Funktion für den Datentyp
int gibt, daß aber sowohl char als auch short durch integrale Promotion in int ver-
wandelt werden können.

Verweise
Siehe Kategorie Variablen und Datentypen, Gültigkeitsbereiche
Siehe Überladen, Überschreiben, Verdecken

Überladung von Funktionen


Beschreibung
C++ erlaubt die Definition mehrerer Funktionen (oder Operatoren) gleichen Namens, sofern die
Funktionen sich in Anzahl oder Typ der Parameter unterscheiden. Die Definition mehrerer
Funktionen gleichen Namens bezeichnet man als Überladung.

Anwendung
Die Überladung von Funktionen wird eingesetzt, um das Verhalten einer Routine
an die ihr übergebenen Parametertypen anzupassen. Der Vorteil für den Program-
mierer besteht darin, daß er nicht mehrere Funktionsnamen für eine Routine zu
vergeben braucht, und der Compiler die Aufgabe übernimmt, die Parameter zu
checken und die richtige Version der Routine aufzurufen.

Warnung
Überladene Funktionen müssen in einem gemeinsamen Gültigkeitsbereich liegen,
sonst findet keine Überladung, sondern die übliche Verdeckung statt.

Beispiele
int max(int a, int b) {
return ( a > b ? a : b);
}
const char* max(const char* s1, const char* s2) {
return (strcmp(s1,s2) ? s1 : s2);
}
int max(int a, char* s) {
return ( a > strlen(s) ? a : strlen(s));
}

162
Überladung von Methoden

Überladung von Methoden


Beschreibung
Methoden werden ebenso überladen, wie oben für Funktionen im Dateibereich ausgeführt
wurde. Besonderheiten ergeben sich jedoch für die Überladung ererbter Methoden, da Basis-
klasse und abgeleitete Klasse unterschiedliche Klassenbereiche darstellen.

Warnung
● Ererbte Funktionen können in abgeleiteten Klassen nicht überladen werden.
● In der abgeleiteten Klasse deklarierte Funktionen verdecken gleichnamige Funk-
tionen der Basisklassen, die weiterhin über den Bereichsoperator aufrufbar sind.
● Soll eine Überladung simuliert werden, müssen die Versionen der Basisklasse
zuerst überschrieben werden.

Beispiele
class basis {
public:
void func(char * s);
void func(char c);
};
class abgeleitet : public basis {
public:
void func(int wert);
}
int main() {
class abgeleitet abg;
[Link]("Test"); // Fehler
[Link]('c'); // Fehler
[Link](3.2); // wird als 3 interpretiert
[Link]::func("Test");
return 0;
}

Überladen, Überschreiben, Verdecken


Überladene Funktionen
● befinden sich im gleichen Gültigkeitsbereich.
● sind anhand ihrer Parameter unterscheidbar.
● dienen zur Anpassung einer Funktion an verschiedene Parametertypen.

163
Sprachkonzepte und Syntax

Überschriebene Methoden
● liegen in verschiedenen Gültigkeitsbereichen, wobei die überschriebene Met-
hode in einer Basisklasse und die überschreibende Methode in einer von der
Basisklasse abgeleiteten Klasse definiert ist.
● haben identische Namen und Parametertypen.
● werden üblicherweise als virtual deklariert.
● dienen der Implementierung polymorphen Verhaltens in Klassenhierarchien.
● sind über den Gültigkeitsbereichoperator weiterhin erreichbar.

Verdeckte Methoden
● liegen in verschiedenen Gültigkeitsbereichen, wobei die überschriebene Me-
thode in einer Basisklasse und die überschreibende Methode in einer von der
Basisklasse abgeleiteten Klasse definiert ist.
● haben nicht-identische Namen und Parametertypen.
● sind über den Gültigkeitsbereichoperator weiterhin erreichbar.

Klassen

Klassen
Beschreibung
C++ basiert auf der Sprache C. Die vollständige Aufwärtskompatibilität garantiert, daß C++ die
Syntax von C vollkommen einschließt. Objektorientiertes Programmieren ist daher nicht gleich-
zusetzen mit Programmieren in C++, sondern beginnt erst mit der Verwendung der objektorien-
tierten Konzepte, um die C++ den C-Standard erweitert. Die wichtigsten dieser Konzepte
(Kapselung, Vererbung, Polymorphie, Templates) gehen zurück auf den neuen Datentyp class.

Anwendung
Klassen dienen dazu, Datenelemente und Elementfunktionen (Methoden) in einem
Datentyp zu kapseln. Sie gestatten es, verschiedene Zugriffsberechtigungen für die
einzelnen Elemente zu vergeben, und können durch Vererbung Klassenhierarchien
aufbauen.

164
Klassen

Syntax
klassentyp klassenname [: BASISKLASSEN]
{
ELEMENTLISTE
} instanzen;
● klassentyp: Als Klassentyp können neben dem Schlüsselwort class auch struct
und union verwendet werden. Die Verwendung der Schlüsselwörter struct und
union beruht darauf, daß in C++ Strukturen und Unions spezielle Klassen dar-
stellen. Dies erleichtert die Verwendung von C-Modulen in C++-Programmen,
sollte den Programmierer aber nicht dazu verführen, beide Konzepte zu vermi-
schen. Es ist empfehlenswert, Klassen stets als class zu deklarieren und Unions
und Strukturen nur gemäß der C-Konvention zu verwenden.
● klassenname: Name der zu deklarierenden Klasse.
● :BASISKLASSEN: Durch Kommata getrennte Liste von Klassen, deren Ele-
mente übernommen (geerbt) werden. Der Zugriff der abgeleiteten Klasse auf
die ererbten Elemente kann durch die Spezifizierer public, protected und priva-
te modifiziert werden. Ein Eintrag in dieser Liste hat folgende Syntax:
[virtual] [public, protected, private] basisklassenname
● ELEMENTLISTE: In der Elementliste werden Datenelemente und Methoden
der Klasse deklariert und unter Umständen auch schon definiert. Der Zugriff
auf die Elemente kann durch die Spezifizierer public, protected und private ge-
regelt werden. Alle Elemente haben ihre Klasse als Gültigkeitsbereich.
● instanzen: Hinter der abschließenden Klammer können durch Kommata ge-
trennt bereits Instanzen, also Variablen der Klassentyps, eingerichtet werden.

Warnung
● Eine Basisklasse muß deklariert sein, bevor sie zur Vererbung herangezogen
werden kann!
● Ein Zugriffsspezifizierer gilt für alle folgenden Klassenelemente bis zum Auf-
treten eines neuen Zugriffsspezifizierers.
● Zugriffsspezifizierer können nicht kombiniert werden.
● Zugriffsspezifizierer dürfen in der Klassendeklaration mehrfach auftauchen.
● Klassenelemente am Anfang der Deklaration, für die kein Zugriffsspezifizierer
angegeben wurde, gelten automatisch als private.

Beispiele
class beispiel {
int wert; // private
public:
beispiel() {wert = 1;}; // Konstruktor
protected:

165
Sprachkonzepte und Syntax

int gebe_wert_aus() {return wert;};


private:
int loesche_wert();
};

Verweise
Siehe Variablen und Datentypen, Strukturen
Siehe Variablen und Datentypen, Unions
Siehe Vererbung und Polymorphie

Klassen und OOP


Beschreibung
Das Konzept, welches hinter den Klassen und allgemein der objektorientierten Programmie-
rung steht, beruht auf der alltäglichen Erfahrung, daß wir die Objekte der realen Welt nach
zwei Maßstäben beurteilen. Einmal nach Merkmalen wie Form und Farbe, zum anderen nach
bestimmten »Verhaltensweisen«, die ein Objekt aufweist, und die beispielsweise festlegen, wie
man mit ihm umzugehen hat. In der objektorientierten Terminologie entsprechen die Merkmale
den Datenelementen und die Verhaltensweisen den Methoden (Elementfunktionen).

Beispiel
Objekte, die gleiche Merkmale und Verhaltensweisen aufweisen, können in einer
Klasse zusammengefaßt werden. So könnte eine Klasse videorecorder folgenderma-
ßen aussehen:
class videorecorder {
/* Merkmale */
char *hersteller;
int anzahl_videokoepfe;
boolean zeitlupe, longplay, zweikanalton;
public:
/* Verhaltensweisen */
void anschalten();
void abspielen();
void aufnahme();
void in_zeitlupe_abspielen();
void ausschalten();
};
Bei der Bildung einer Variablen der Klasse – im folgenden als Instanzbildung
bezeichnet – werden den Merkmalen Werte zugewiesen. Auf diese Weise entsteht
durch Spezialisierung eine Instanz, die nur noch einen besonderen Videorecorder
repräsentiert. (Ein weiteres Beispiel wäre die Klasse Mensch und ihre Instanzen, näm-
lich jeder einzelne von uns – die Individuen. Eine Geburt wäre folglich eine Instanz-
bildung.)

166
Kapselung

Verweise
Siehe Kapselung
Siehe Instanzbildung

Kapselung
Beschreibung
Die Zusammenfassung von Datenelementen und Methoden wird als Kapselung bezeichnet.
Zudem verbinden sich mit dem Begriff noch zwei weitere Designkriterien:
– Information hiding und
– Abgeschlossenheit

Information hiding
Klassen sollten vornehmlich über ihre Methoden angesprochen werden. Diese
Funktionen bilden die Schnittstelle zwischen Klasse und Programm. (Die genaue
Festlegung der Schnittstelle erfolgt über die Vergabe von Zugriffsspezifizierern.)
Nach der Implementierung der Klasse ist es für den Programmierer wichtig, daß er
die Klasse nur noch über ihre Schnittstelle einzusetzen braucht, ohne sich weitere
Gedanken um deren Implementierung machen zu müssen. Für die fehlerlose Bear-
beitung der Funktionsaufrufe und das korrekte Verhalten der Klasse, trägt diese
selbst Sorge. Wurde zum Beispiel eine Klasse videorecorder implementiert, um
Videorecorder über den Computer anzusteuern, braucht der Programmierer nur
noch eine Instanz der Klasse zu bilden und kann danach die Instanz einsetzen wie
einen realen Videorecorder:
my_recorder.anschalten();
my_recorder.in_zeitlupe_abspielen();
my_recorder.ausschalten();
Die Ansteuerung des Videorecorders über die parallele Schnittstelle oder die Kon-
trolle, ob der Videorecorder überhaupt über Zeitlupe verfügt, nimmt die Klasse
selbst vor, d. h.,sie versteckt solche Details vor dem Programmierer und entlastet
ihn dadurch.

Abgeschlossenheit
Aus der Forderung des Information hidings ergibt sich das Kriterium der Abge-
schlossenheit. Die Schnittstelle einer Klasse sollte möglichst vollständig sein, in dem
Sinne, daß die Klasse auch sinnvoll eingesetzt werden kann. Eine Klasse videorecor-
der, die über keine Funktion in_zeitlupe_abspielen() verfügt, wäre von vornherein
zur Bedienung von Videorecordern mit Zeitlupe ungeeignet.

167
Sprachkonzepte und Syntax

Umgekehrt sollten in einer Klasse nur Daten und Funktionen enthalten sein, die die
Objekte der Klasse auch wirklich kennzeichnen. Eine Methode berechne_bruch()
würde in der Klasse videorecorder keinen Sinn machen.

Verweise
Siehe Praxisteil, Kategorie Klassen

Datenelemente
Beschreibung
Variablen, die innerhalb einer Klasse definiert werden, stellen die Datenelemente der Klasse
dar.

Anwendung
Wird eine Instanz von der Klasse gebildet, wird der Instanz Speicher für die Daten-
elemente zur Verfügung gestellt. Jede Instanz hat also ihre eigene Kopie der Daten-
elemente, die man daher auch Instanzvariablen nennt. Gleichzeitig wird die
Instanzbildung dazu genutzt, die Datenelemente zu initialisieren. Diese Aufgabe
übernimmt der Konstruktor. Klassen stellen einen eigenen Gültigkeitsbereich dar,
d. h., die Instanzvariablen verfallen mit ihrer Instanz (wofür der Destruktor Sorge
trägt), und Namen aus anderen Gültigkeitsbereichen werden verdeckt. Neben der
Deklaration von Datenelementen bekannter Typen ist es auch möglich, innerhalb
einer Klasse eine lokale Typdefinition vorzunehmen.

Warnung
Datenelemente
● können als public, protected oder private deklariert werden.
● werden bei der Instanzbildung eingerichtet und zusammen mit der Instanz auf-
gelöst.
● können als static, const, volatile oder mutable deklariert werden.

Beispiele
class demo {
int anzahl; // private Daten
int *feld;
public:
char *str; // public Daten
...

168
Statische Datenelemente

Verweise
Siehe Konstruktor und Destruktor
Siehe Zugriffsspezifizierer

Statische Datenelemente
Beschreibung
Statische Datenelemente werden bei der Instanzbildung nicht kopiert. Statt dessen greifen alle
Instanzen auf die gleiche Variable zu.

Anwendung
Statische Elemente müssen außerhalb der Klasse, im umgebenden namespace (oder
Dateibereich), definiert werden und können nicht nur über Instanzen, sondern auch
über den Klassennamen angesprochen werden:

Warnung
Statische Elemente können nicht als auto, register oder extern deklariert werden.

Beispiele
class Demo {
public:
static int instanzenzaehler;

Demo() {instanzenzaehler++;}
~Demo() {instanzenzaehler--;}
};
int Demo::instanzenzaehler = 0;

int main() {
Demo lok;
cout << Demo::instanzenzaehler << endl;
cout << [Link] << endl;
return 0;
}

Verweise
Siehe Statische Methoden

169
Sprachkonzepte und Syntax

Konstante Datenelemente
Beschreibung
Datenelemente, die als const deklariert werden, können nach der Instanzbildung nicht mehr
verändert werden.

Warnung
const-Datenelemente müssen in der Konstruktorliste initialisiert werden.

Beispiele
class Demo {
public:
const int j; // konstante Instanzvariable
Demo() : j(2) // Initialisierung
{
...
};

Verweise
Siehe Konstante Methoden
Siehe Kategorie Konstanten

Klasseninstanzen als Datenelemente


Beschreibung
Instanzvariablen können auch vom Datentyp einer Klasse sein, man spricht dann auch von ein-
gebetteten Objekten.

Anwendung
Eingebettete Objekte werden im Zuge der Instanzbildung des ihnen übergeordneten
Objekts erzeugt und mit diesem aufgelöst.
Zur Einrichtung des eingebetteten Objekts muß ein Konstruktor des eingebetteten
Objekts aufgerufen werden. Dies kann ein Standardkonstruktor sein, der Program-
mierer muß sich dann nicht um die Einrichtung kümmern. Es kann auch ein Kon-
struktor mit Argumenten sein, der Programmierer muß dann den Konstruktor des
übergordneten Objekts um eine Konstruktorliste erweitern, in der der Konstruktor
des eingebetteten Objekts aufgerufen wird. (Beachten Sie, daß der Konstruktor
über den Objektnamen und nicht wie bei Basisklassen über den Klassennamen auf-
gerufen wird.)
Zur Auflösung des eingebetteten Objekts wird sein Destruktor aufgerufen.

170
Klasseninstanzen als Datenelemente

Warnung
● Eine Klasse kann keine Instanzen von Klassen als Element enthalten, wenn
diese Klassen nicht zuvor definiert wurden.
● Da die Definition einer Klasse mit dem Semikolon abschließt, folgt daraus,
daß eine Klasse keine Instanz ihres eigenen Typs als Element enthalten kann.
Wohl aber ist es möglich, Zeiger oder Referenzen auf nicht definierte Klassen
zu definieren, sofern der Klassenname bekannt ist.
● Die umliegende Klasse hat keine besonderen Zugriffsrechte auf die Elemente
des eingebetteten Objekts.

Beispiele
Zeiger auf Objekte von noch nicht definierten Klassen:
class demo;
class beispiel {
int a;
class beispiel falsch; // kann von Compiler nicht
// aufgelöst werden
class beispiel* richtig;
class demo& auch_richtig;
};
Instanziierung eingebetteter Objekte durch den Standardkonstruktor:
class A {
public:
int i;
A() {i = 1;} // Standardkonstruktor
};
class B {
public:
int n;
A obj;
B() {n = 2;}
};
Instanziierung eingebetteter Objekte über Konstruktorliste:
class A {
public:
int i;
A(int i_par) {i = i_par;}
};
class B {
public:
int n;
A obj;
B(int p1, int p2) : obj(p1) {n = p2;}
};

171
Sprachkonzepte und Syntax

Verweise
Siehe Lokale und verschachtelte Klassen
Siehe Konstruktor
Siehe Vererbung und Polymorphie, Vererbung versus Einbettung

Lokale und verschachtelte Klassen


Beschreibung
Klassen, die im Anweisungsteil einer Funktion definiert werden, werden als lokale Klassen
bezeichnet.
Klassen, die im Definitionsteil einer Klasse definiert werden, werden als verschachtelte oder
eingeschlossene Klassen bezeichnet.

Warnung
● Eine eingeschlossene Klasse kann Typen und statische Elemente der einschlie-
ßenden Klasse direkt benutzen.
● Eingeschlossene Klassen dürfen keine statischen Elemente enthalten.
● Die eingeschlossene Klasse hat keine besonderen Zugriffsrechte auf die Ele-
mente der einschließenden Klasse, d. h., sie kann nur über Instanzen der einge-
schlossenen Klasse auf deren Elemente zugreifen (Ebenso hat auch die
einschließende Klasse keine besonderen Zugriffsrechte auf die eingeschlossene
Klasse).

Beispiele
int i;
class global {
static int n;
public:
int i;
static float f;
class intern {
void func(global &glob) {
i = 3; // Fehler
f = 3; // korrekt
::i = 3; // i aus Dateibereich
glob.i = 3; // i aus Klasse global
n = 3; // Fehler
}
...

172
Methoden

Verweise
Siehe Klasseninstanzen als Datenelemente

Methoden
Beschreibung
Funktionen, die als Elemente einer Klasse definiert werden, bezeichnet man als Methoden.

Anwendung
Methoden können sowohl innerhalb als auch außerhalb der Klassendeklaration
definiert werden.
● Methoden, die innerhalb der Klassendefinition definiert werden, werden auto-
matisch als inline interpretiert. Auch wenn das Schlüsselwort inline nur als
Empfehlung für den Compiler gedacht ist, ergibt sich daraus, daß innerhalb
einer Klassendefinition nur kurze Funktionen definiert werden sollten. Zum
einen, um Speicherplatz zu sparen, zum anderen, um die Klassendefinition
übersichtlich zu halten.
● Bei der Definition außerhalb der Klassendefinition muß der Klassenname mit
dem Bereichsoperator vorangestellt werden.

Definition innerhalb der Klassendefinition:


class Demo {
int wert;
public:
Demo() {wert = 1;}
int gebe_wert_aus() {return wert;}
};

Definition außerhalb der Klassendefinition:


class Demo {
int wert;
public:
Demo();
int func();
};
inline Demo::Demo() {wert = 1;}
int Demo::func() {
...
}

173
Sprachkonzepte und Syntax

Warnung
Methoden
● können als public, protected oder private deklariert werden.
● haben Zugriff auf alle Elemente der Klasse.
● stellen neben Friends die einzige Möglichkeit dar, auf private Elemente ihrer
Klasse zuzugreifen.
● können als virtual deklariert werden.
● können als inline deklariert werden.
● können als const deklariert werden. Methoden, die als const deklariert sind,
sind die einzigen Methoden, die von const-deklarierten Instanzen aufgerufen
werden können. (Das Schlüsselwort const wird der Parameterliste nachge-
stellt).
● können als volatile deklariert werden. Methoden, die als volatile deklariert
sind, sind die einzigen Methoden, die von volatile-deklarierten Instanzen auf-
gerufen werden können. (Das Schlüsselwort volatile wird der Parameterliste
nachgestellt).
● können nur von Methoden der gleichen Klasse überladen werden.

Verweise
Siehe Überladung
Siehe Kategorie Vererbung und Polymorphie, Überschreibung und virtuelle Metho-
den

Statische Methoden
Beschreibung
Statische Methoden sind Methoden, die mit dem Schlüsselwort static deklariert werden. Stati-
sche Methoden sind ebenso wie statische Datenelemente klassen- und nicht instanzspezifisch.
Statische Methoden besitzen keinen this-Zeiger und können daher nur andere statische Ele-
mente (Daten wie Methoden) aufrufen.

Anwendung
Statische Methoden können über Instanzen oder den Klassennamen aufgerufen
werden.

Warnung
Statische Methoden können nicht als virtual deklariert werden.

174
Konstante Methoden

Beispiele
class Demo {
private:
static int standardwert;
public:
static void std_setzen(int i) {
if( i > 0 && i < 100 )
standardwert = i;
}
};
int Demo::standardwert = 1;
int main()
{
Demo obj1, obj2;
Demo::std_setzen(33);
return 0;
}

Verweise
Siehe Statische Datenelemente

Konstante Methoden
Beschreibung
Konstante Methoden sind Methoden, die mit dem Schlüsselwort const deklariert werden.
Methoden, die als const deklariert werden, können Elementdaten nicht ändern (es sei denn,
diese sind explizit als mutable deklariert) und können Zeiger oder Referenzen auf Elementda-
ten nur als const zurückgeben.

Anwendung
const-Methoden sind die einzigen Methoden, die von const-deklarierten Instanzen
aufgerufen werden können. (Manche Compiler geben bei Zuwiderhandlung aller-
dings nur eine Warnung aus).
Das Schlüsselwort const wird der Parameterliste nachgestellt.

Beispiele
class Demo {
public:
int i;
const int j;
mutable int n;
Demo() : j(2) {} // Initialisierung
void inkr() const {
i++; // Fehler

175
Sprachkonzepte und Syntax

j++; // Fehler
n++; // ok
}
void func() {...}
};
Konstante Klasseninstanzen:
const demo obj2;
[Link](); // Fehler
[Link](); // o.k.

Verweise
Siehe Konstante Datenelemente

Zugriffsspezifizierer
Beschreibung
Die Zugriffsspezifizierer public, private und protected regeln, wie von innerhalb und außer-
halb der Klasse auf deren Elemente zugegriffen werden kann.

Anwendung
Die Zugriffsspezifizierer sind daher ein wichtiges Instrument der Kapselung. Erst
durch diese Spezifizierer kann eine Klasse vor Mißbrauch geschützt werden. Die
Zugriffsspezifizierer werden sowohl bei der Klassendefinition wie auch bei der Ver-
erbung eingesetzt.

Zugriffsspezifizierer bei der Klassendefinition


Innerhalb der Klassendefinition kann man die Zugriffsspezifizierer verwenden, um
nachfolgend definierten Klassenelementen einer Zugriffsebene zuzuordnen.
class demo {
...
public:
...
protected:
...
private:
...
};

176
Zugriffsspezifizierer

Spezifizierer Bedeutung
public Das Element kann von jeder Methode der eigenen und abgeleiteten Klas-
sen benutzt werden. Der Zugriff von außen erfolgt über den Namen der
Instanz und einem der Zugriffsoperatoren:
instanz_name.elementname
referenz_der_instanz.elementname
zeiger_auf_instanz->element_name
private Das Element kann nur von Methoden und Friends der Klasse, in der es
deklariert wurde, benutzt werden.
protected Es gilt das gleiche wie für private. Zusätzlich ist jedoch die Benutzung
durch Methoden von Klassen, die von der deklarierten Klasse abgeleitet
sind, möglich. Gibt es keine abgeleiteten Klassen, sind private und pro-
tected identisch.

Zugriffsspezifizierer bei der Vererbung


Im Zuge der Vererbung kann man die Zugriffsspezifizierer verwenden, um den
Zugriff über Instanzen der abgeleiteten Klasse auf die geerbten Elemente zu ver-
schärfen.
class abgeleitet : public basisklasse
{
...

Spezifizierer Bedeutung
public Für die geerbten Elemente gelten die gleichen Zugriffsrechte, die in der
Basisklasse festgelegt wurden.
private Alle geerbten Elemente sind von außen als private anzusehen.
protected public-Elemente werden als protected-Elemente angesehen.

Warnung
● Ein Zugriffsspezifizierer gilt für alle folgenden Klassenelemente bis zum Auf-
treten eines neuen Zugriffsspezifizierers.
● Zugriffsspezifizierer können nicht kombiniert werden.
● Zugriffsspezifizierer dürfen in der Klassendeklaration mehrfach auftauchen.
● Klassenelemente am Anfang der Deklaration, für die kein Zugriffsspezifizierer
angegeben wurde, gelten automatisch als private.
● Zu den Zugriffsspezifizierern im weiteren Sinne zählt auch das Schlüsselwort
friend (siehe Zugriff von außerhalb der Klasse).

177
Sprachkonzepte und Syntax

Zugriff auf Klassenelemente


Prinzipiell werden Klassen so ausgelegt, daß sie ihre Datenelemente durch die
Deklaration als private verstecken und Manipulationen nur über eine Auswahl
bestimmter als public deklarierter Methoden ermöglichen.
In der Praxis gibt es durch die Verwendung der Zugriffsspezifizierer bei der Klas-
sendeklaration sowie bei der Vererbung und des Zugriffsspezifizierers friend eine
Vielzahl von Situationen mit unterschiedlichen Zugriffsberechtigungen. Um den
Überblick zu behalten, werden diese Situationen in den folgenden Abschnitten
zusammengefaßt.

Verweise
Siehe nachfolgende Abschnitte
Siehe Vererbung und Polymorphie, Zugriffsbeschränkung bei der Vererbung

Zugriff innerhalb der Klasse


el_name

Beschreibung
Zugriff innerhalb einer Klasse bedeutet, daß innerhalb des Funktionskörpers von Methoden auf
andere Elemente (Daten oder Funktionen) der eigenen Klasse zugegriffen wird. Dies ist der
innerste Bereich, der praktisch keinen Beschränkungen unterliegt. Der Zugang zu den Elemen-
ten erfolgt direkt über deren Namen.

Warnung
● Methoden, die als const deklariert sind, können auf alle Datenelemente zugrei-
fen, aber nur mutable-Datenelemente verändern.
● Statische Methoden können nur statische Elementdaten direkt ansprechen.
(Dies liegt daran, daß statische Methoden keinen this-Zeiger besitzen.) Nicht-
statische Elemente müssen über eine existierende Instanz (die beispielsweise
als Argument übergeben werden kann) angesprochen werden.
● Für geerbte Elemente aus Basisklassen gelten die Zugriffsrechte, die in der Ba-
sisklasse festgelegt wurden.

Beispiele
class demo {
private:
int wert1, wert2;
int func1() {return wert1*wert2;}

178
Zugriff von außerhalb der Klasse

public:
...
void func2(int i) {
wert1=i+1;
wert2 = func1();
}
};

Verweise
Siehe nachfolgende Abschnitte
Siehe this-Zeiger

Zugriff von außerhalb der Klasse


objekt.el_name

Beschreibung
Von außerhalb kann auf Elemente der Klasse T nur über eine Instanz der Klasse T in Verbin-
dung mit einem der Operatoren . -> .* ->* oder über Friends der Klasse zugegriffen werden.

Zugriff über Instanz .,->


Der Zugriff unterliegt den Einstellungen durch die Modifizierer public, protected
und private, d. h. Elemente, die in der Klasse als protected oder private deklariert
sind (dies gilt auch für ererbte Elemente), können auf diese Weise nicht angespro-
chen werden.
class demo {
int wert1; // standardmäßig private
int func1();
public;
int wert2;
int func2();
};
int main() {
class demo d, *ptr_d;
int dummy;
dummy = d.wert1; // Fehler
dummy = ptr_d->func1(); // Fehler
dummy = d.wert2;
dummy = ptr_d->func2();
}

179
Sprachkonzepte und Syntax

Zugriff über Zeiger auf Klassenelemente .*,->*


Auch hier gilt, daß nur auf public-Elemente zugegriffen werden kann. Wie die Syn-
tax zur Definition, Initialisierung und Dereferenzierung von Zeigern auf Klassen-
elemente aussieht, entnehmen Sie bitte dem Abschnitt Operatoren, Datenzugriff.

Zugriff über Friends friend


Manchmal ist es sinnvoll, die strengen Regeln der Zugriffsberechtigungen durch
public, protected und private zu umgehen und einer beliebigen Funktion (also nicht
bloß Klassenfunktionen) Zugriff auf protected oder private Elemente zu erteilen.
Das Schlüsselwort friend ermöglicht dies.
Um eine Friend-Funktion einzurichten, bedarf es zweierlei:
● Erstens muß die Funktion in der Klasse, auf die sie Zugriff haben soll, als fri-
end deklariert werden, und
● Zweitens muß eine Referenz oder Instanz der Klasse an die Funktion überge-
ben werden.
#include <iostream>
using namespaces std;

class demo {
int wert;
friend int func(demo&); // Friend-Deklaration
};
// Friend-Funktion
int func(demo& objekt) {
return [Link];
}

int main() {
class demo d;
cout << func(d);
return 0;
}

Warnung
● Beachten Sie die Feinheit, daß die Deklaration als friend in der Klasse vorge-
nommen werden muß. Die Klasse bestimmt also selbst, welche Funktionen
friend sind und welche nicht, und kann ihre Daten immer noch vor unkontrol-
liertem Gebrauch schützen.
● Private Elemente, die über keine public-Methoden verfügen, können über fri-
end-Funktionen erreicht werden.

180
Zugriff auf Basisklassenelemente

● Neben der Deklaration einzelner Funktionen als friend können Sie auch sämt-
liche Funktionen einer Klasse auf einen Schlag als friend deklarieren, indem
Sie die ganze Klasse als friend deklarieren.

Verweise
Siehe Kategorie Operatoren, Datenzugriff

Zugriff auf Basisklassenelemente


Beschreibung
Für abgeleitete Klassen muß man zwischen den eigenen und den geerbten Elementen sowie
dem Zugriff aus den Methoden der abgeleiteten Klasse oder dem Zugriff von außen unterschei-
den.

Zugriff aus der abgeleiteten Klasse


Die Methoden, die in der abgeleiteten Klasse deklariert sind, können sowohl auf
die eigenen als auch die geerbten Elemente direkt über den Elementnamen zugrei-
fen.
Während der Zugriff auf die eigenen Elemente jedoch keinerlei Beschränkungen
unterliegt, wird der Zugriff auf die geerbten Elemente durch die Zugriffsspezifizie-
rer aus der Basisklassendeklaration geregelt. Eine Methode der abgeleiteten Klasse
hat Zugriff auf public- und protected-Elemente, nicht aber auf private-Elemente.
Geerbte private-Elemente können in den Methoden der abgeleiteten Klasse nur auf
dem Umweg über geerbte public- oder protected-Methoden angesprochen werden.
class Basis {
int basis_priv;
protected:
int basis_prot;
public:
int basis_pub;
};
class Abgeleitet : private Basis {
int abg_priv;
public:
void abg_func(int n)
{
basis_pub = n;
basis_prot = n;
//basis_priv = n; // Fehler, kein Zugriff
}
};

181
Sprachkonzepte und Syntax

Zugriff von außen


Nach außen gibt es keinen Unterschied zwischen den eigenen und den geerbten Ele-
menten einer Klasse. Wichtig ist nur, welche Zugriffsrechte die abgeleitete Klasse
für die geerbten Elemente nach außen weitergibt.
Grundsätzlich gelten die Zugriffsrechte, die in der Basisklasse, aus der die Elemente
stammen, spezifiziert wurden. Man kann aber durch die Zugriffsspezifizierer der
Vererbung die Zugriffsrechte verschärfen (siehe Abschnitt Vererbung und Polymor-
phie, Zugriffsbeschränkung bei der Vererbung).
Für einzelne Elemente kann man die bei der Vererbung eingeengten Zugriffsrechte
durch Redeklaration oder mit Hilfe des Schlüsselworts using wieder auflockern.

Zugriff auf verdeckte/überschriebene Methoden


Wird eine geerbte Methode in der abgeleiteten Klasse durch Deklaration einer
gleichnamigen Methode mit gleicher Signatur überschrieben oder durch die Dekla-
ration einer gleichnamigen Methode mit abweichender Signatur verdeckt, kann
man mit Hilfe des Gültigkeitsbereichsoperators weiterhin auf die Version der Basis-
klasse zugreifen.
Dies funktioniert ebenso gut von innerhalb wie von außerhalb der Klasse.
class Basis {
public:
void func(int) {cout << "Basis-Version" << endl;};
};
class Abgeleitet : public Basis {
public:
void func(char*) {
// Zugriff auf verdeckte Basisklassenversion
Basis::func(3);
cout << "abgel. Version" << endl;
};
};
int main() {
class Abgeleitet abg;
// Zugriff auf verdeckte Basisklassenversion
[Link]::func(3); // ok
return 0;
}

Verweise
Siehe Kategorie Vererbung und Polymorphie, Zugriffsbeschränkung und Zugriffs-
rechte

182
Der Konstruktor

Der Konstruktor
klassenname() {}

Beschreibung
Jede Instanzbildung eines Klassenobjekts ist mit dem Aufruf eines Konstruktors verbunden.

Anwendung
Der Programmierer kann im Anweisungsteil des Konstruktors für die Initialisierung
der Datenelemente und für Eingangsarbeiten (beispielsweise der Reservierung von
dynamischem Speicher) sorgen.
Durch Definition eines oder mehrerer eigener Konstruktoren (Überladung) kann
die Instanzbildung gesteuert und an die Übergabe verschiedener Argumenttypen
angepaßt werden.

Der Standardkonstruktor
Um sicherzustellen, daß jede Klasse über einen Konstruktor verfügt, weist der
Compiler Klassen ohne explizit deklarierten Konstruktor einen Standardkonstruk-
tor zu (Konstruktor, der ohne Argument aufgerufen werden kann).
Wird ein Konstruktor explizit definiert, steht der Standardkonstruktor des Compi-
lers nicht mehr zur Verfügung; der Programmierer kann aber einen eigenen Stan-
dardkonstruktor definieren.
Der Standardkonstruktor vereinfacht die Einrichtung eingebetteter und geerbter
Objekte sowie von Arrays von Klassenobjekten, die ansonsten nur durch Angabe
von Konstruktorlisten bzw. Initialisierungslisten zu bewerkstelligen ist.

Warnung
● Ein Konstruktor hat immer den gleichen Namen wie seine Klasse.
● Ein Konstruktor hat keinen Rückgabewert (auch nicht void).
● Konstruktoren können nicht als virtual, static, const, mutable oder volatile
deklariert werden.
● Konstruktoren können überladen werden. Die Überladung wird meist dazu ge-
nutzt, dem Konstruktor Argumente für die Initialisierung der Datenelemente
der Klasse zu übergeben.
● Konstruktoren werden nicht vererbt.
● Es können keine Zeiger auf Konstruktoren definiert werden.
● Konstruktoren können nach der Instanzbildung nicht mehr aufgerufen wer-
den.

183
Sprachkonzepte und Syntax

● Konstruktoren, die mit genau einem Argument aufgerufen werden können,


können implizite Konvertierungen vom Argumenttyp in den Typ ihrer Klasse
durchführen. Der Compiler nimmt diese Konvertierung in das Repertoire sei-
ner Standardkonvertierungen auf. Um ungewollte Standardkonvertierungen zu
verhindern, kann ein solcher Konstruktor als explicit deklariert werden.

Beispiele
class demo {
int privat;
public:
demo(int i) {privat = i;}
explicit demo(float f) {privat = (int) f;};
};
int main() {
class demo instanz(100);
class demo instanz2 = 100;//implizite Konvertierung
class demo instanz3(3.2);
class demo instanz4 = 3.2;//Fehler: explicit
class demo instanz5; //Fehler, Standardkonstruktor
//nicht mehr verfügbar
return 0;
}

Verweise
Siehe Kopierkonstruktor
Siehe Destruktor
Siehe Klasseninstanzen als Datenelemente
Siehe Kategorie Vererbung und Polymorphie, Vererbung und Konstruktor

Der Kopierkonstruktor
klassenbezeichner(klassenbezeichner&)

Beschreibung
Der Kopierkonstruktor ist ein Konstruktor, der Instanzen seiner Klasse auf der Grundlage ande-
rer Instanzen der Klasse erzeugt. Die Instanz, die als Grundlage für die neu anzulegende
Instanz verwendet werden soll, wird dem Konstruktor als Parameter übergeben.

184
Der Kopierkonstruktor

Anwendung
Der Kopierkonstruktor wird aufgerufen, wenn Sie eine Klasseninstanz mit einer
anderen Klasseninstanz (der gleichen Klasse) initialisieren. Wurde innerhalb der
Klasse kein eigener Kopierkonstruktor deklariert, wird der Standardkopierkon-
struktor aufgerufen, der die Klassenelemente 1:1 kopiert.
Der Kopierkonstruktor ist eine von zwei Möglichkeiten, Klasseninstanzen zu
kopieren. Die zweite Option ist der Zuweisungsoperator =, der ebenfalls als 1:1-
Kopierer vordefiniert ist und bei Bedarf überladen werden muß.
Beachten Sie, daß Kopierkonstruktoren implizit auch bei der Übergabe von Klas-
senobjekten an Funktionen/Methoden und bei der Zurücklieferung von Klassenob-
jekten als Rückgabewerte von Funktionen/Methoden aufgerufen werden (sofern
nicht Zeiger oder Referenzen verwendet werden).

Warnung
1:1-Kopieren wie vom Standard-Kopierkonstruktor vorgenommen, führt meist zu
Fehlern, wenn die Klasse Zeiger enthält. Dies liegt einfach daran, daß für einen
Zeiger die in dem Zeiger aufbewahrten Adressen kopiert werden, so daß nach der
Kopierinitialisierung die beiden Zeiger der Vorlage und der Kopie auf das gleiche
Objekt verweisen.

Beispiele
#include <iostream>
using namespace std;

class demo {
int i;
int* p;
public:
demo(int wert) {
i = wert;
p= &i;
}
demo(const demo& inst) { // Kopierkonstruktor
i = inst.i; p = &i;
}
};

int main() {
demo a(3);
demo b(a); // Verwendung des Kopierkonstruktors

return 0;
}

185
Sprachkonzepte und Syntax

Verweise
Siehe Konstruktor

Der Destruktor
~klassenname() {}

Beschreibung
Destruktoren werden automatisch aufgerufen, wenn Klasseninstanzen ihre Gültigkeit verlieren
(beispielsweise bei Verlassen des Gültigkeitsbereichs oder bei delete-Aufrufen für Zeiger auf
Klasseninstanzen). Sie lösen die Instanz auf und geben den reservierten Speicher frei.

Warnung
Für Destruktoren gelten ähnliche Regeln wie für Konstruktoren:
● Destruktoren tragen immer den Namen ihrer Klasse, jedoch mit vorangehen-
der Tilde.
● Ein Destruktor hat keinen Rückgabewert (auch nicht void).
● Destruktoren können nicht als static, const, mutable oder volatile deklariert
werden.
● Eine Klasse ohne explizit deklarierten Destruktor bekommt einen Standardde-
struktor zugewiesen.
● Destruktoren werden nicht vererbt.
● Es können keine Zeiger auf Destruktoren definiert werden.
Destruktoren unterscheiden sich von Konstruktoren:
● Destruktoren können keine Argumente übergeben werden, woraus folgt:
● Destruktoren können überschrieben, aber nicht überladen werden.
● Destruktoren können als virtual deklariert werden.
● Basisklassen sollten im Zweifelsfalle einen virtuellen Destruktor definieren.
● Destruktoren von Klassen, die von Basisklassen mit virtuellem Destruktor ab-
geleitet sind, sind automatisch virtuell.
● Destruktoren können explizit aufgerufen werden, was aber selten notwendig ist.

Verweise
Siehe Konstruktor

186
Standardmethoden

Standardmethoden
Es gibt 5 Methoden, für die der Compiler automatisch Standardversionen erzeugt,
wenn die Klasse keine eigenen Implementierungen vorsieht.
● Standardkonstruktor
● Destruktor
● Kopierkonstruktor
● Zuweisungsoperator
● Adreßoperator (liefert den Wert des this-Zeigers zurück).

Der this-Zeiger
this

Beschreibung
Der this-Zeiger ist ein vom Compiler definierter Zeiger, der in allen nicht-statischen Methoden
einer Klasse verfügbar ist und jeweils auf das aktuelle Objekt der Klasse verweist, über das die
Methode aufgerufen wurde.

Anwendung
Werden mehrere Instanzen einer Klasse gebildet, bekommt jede Instanz eine eigene
Kopie der Datenelemente der Klasse. Die Methoden der Klasse stehen aber nur ein-
mal im Arbeitsspeicher und werden von allen Instanzen einer Klasse gemeinsam
benutzt. Da die Methoden üblicherweise auf den Elementdaten der Klasse operie-
ren und diese instanzspezifisch sein sollen, muß sichergestellt werden, daß die
jeweilige Methode nur auf die Daten zugreift, die zur aufrufenden Instanz gehören.
Der Compiler weist aus diesem Grunde jeder Instanz einen Zeiger auf sich selbst zu
– den this-Zeiger. Bei jedem Aufruf einer Methode wird dieser Zeiger automatisch
an die Methode übergeben. Somit ist der this-Zeiger in jeder Methode verfügbar
(mit Ausnahme statischer Methoden).

Beispiele
#include <iostream>
using namespace std;

class demo {
public:
void func() { cout << this; }
};

187
Sprachkonzepte und Syntax

int main() {
class demo d1;
cout << "This-Zeiger der Instanz d1 = ";
[Link]();
return 0;
}

Verweise
Siehe Klassen, Methoden

Instanzbildung
klassentyp obj;

Beschreibung
Als Instanzbildung bezeichnet man die Einrichtung von Klassenobjekten (Variablen eines Klas-
sentyps). Bei der Instanzbildung wird ein konkretes Objekt einer Klasse gebildet, indem den
Datenelementen Werte zugeordnet werden. Für die Einrichtung des Speichers und die Initiali-
sierung der Datenelemente ist der Konstruktor verantwortlich, der automatisch bei der Instanz-
bildung aufgerufen wird.

Bildung konstanter Instanzen


Wird eine Instanz bei ihrer Einrichtung als const deklariert, bedeutet dies, daß alle
Datenelemente, die in der Klasse nicht explizit als mutable deklariert sind, const
sind, d. h., ihr Wert kann nicht verändert werden. Auch können nur als const dekla-
rierte Methoden aufgerufen werden.

Instanzbildung und Arrays


Bei der Initialisierung von Klassen-Arrays (Arrays von Klassenobjekten) muß jedes
Array-Element durch einen Konstruktor eingerichtet werden. Dies kann durch
einen Standardkonstruktor (Konstruktor ohne Parameter) geschehen oder durch
eine Initialisierungsliste und expliziten Aufruf für jedes Array-Element:

Beispiele
class demo {
int privat;
public:
demo() {}; // Standardkonstruktor
demo(int i) {privat = i;}
};

int main() {

188
Vererbung

class demo d[2] = {demo(10), demo(100)}; // Einrichtung mit


// Initialisierungsliste
const class demo e[200]; // Einrichtung mit Standardkonstruktor
return 0;
}

Verweise
Siehe Konstruktor

Vererbung und Polymorphie

Vererbung
Beschreibung
Vererbung ist ein weiteres, ganz wesentliches Konzept der objektorientierten Programmierung,
welches es ermöglicht, neue Klassen auf der Basis bereits vorhandener Klassen zu definieren.

Anwendung
Die einfachste Form der Vererbung besteht aus einer Basisklasse und einer abgelei-
teten Klasse. Durch die Vererbung wird festgelegt, daß die abgeleitete Klasse –
zusätzlich zu den in ihrer Definition aufgeführten Eigenschaften (Datenelemente
und Methoden) – über sämtliche Elemente der Basisklasse verfügt. Auf diese Weise
kann praktisch jede Klasse von jeder anderen Klasse abgeleitet werden, was jedoch
nicht immer sinnvoll ist.
Zusätzlich zu den mit dem Klassenkonzept und der Kapselung verbundenen Vortei-
len bringt die Vererbung weitere Annehmlichkeiten mit sich:
● Gemeinsame Eigenschaften von Klassen brauchen durch Verlegung in eine Ba-
sisklasse nur einmal implementiert zu werden, wodurch auch die Wartbarkeit
des Quellcodes erleichtert wird.
● Umgekehrt gewährt die Ableitung von Basisklassen ein einheitliches Erschei-
nungsbild verwandter Klassen.
Verschiedene Konzepte erlauben es, die Gestaltung von Klassenhierarchien flexibel
zu gestalten:
● Polymorphie (virtuelle Funktionen)
● Friends

189
Sprachkonzepte und Syntax

Andere Konzepte dienen dazu, die Klassen vor Mißbrauch zu schützen und Klas-
senhierarchien strenger zu organisieren:
● Zugriffsmodifizierer
● abstrakte Klassen

Syntax
class klassenname : BASISKLASSENLISTE
{
Liste der Klassenelemente
};
● BASISKLASSENLISTE: In der Basisklassenliste werden, durch Kommata von-
einander getrennt, die Basisklassen aufgeführt, deren Eigenschaften geerbt
werden sollen. Ein Eintrag in dieser Liste hat folgende Syntax:
[virtual] [public, protected, private] Basisklassenname
● Die Zugriffsspezifizierer public, protected und private regeln bei der Vererbung
nicht den Zugriff aus den Methoden der abgeleiteten Klassen auf die geerbten
Elemente (dies wird schon durch die Zugriffsspezifizierer in der Deklaration
der Basisklasse geregelt), sondern welche Zugriffsrechte die abgeleitete Klasse
für die geerbten Elemente nach außen weitergibt (beispielsweise, wenn über
eine Instanz der abgeleiteten Klasse auf diese Elemente zugegriffen wird, oder
wenn die abgeleitete Klasse selbst als Basisklasse benutzt wird). Wird kein Zu-
griffsspezifizierer angegeben, wird die Klasse private vererbt.
● Das Schlüsselwort virtual ist nur für die Mehrfachvererbung von Bedeutung.

Warnung
Eine Basisklasse muß deklariert sein, bevor sie zur Vererbung herangezogen werden
kann!
Sinnvolle Klassenhierarchien gründen darauf, daß
● in Basisklassen die gemeinsamen Eigenschaften der abgeleiteten Klassen zu-
sammengefaßt sind,
● abgeleitete Klassen natürliche Erweiterungen und/oder Spezialisierungen ihrer
Basisklassen sind,
● man Objekte der abgeleiteten Klassen immer auch als Objekte ihrer Basisklas-
sen ansehen kann.

Beispiele
class Basis {
public:
void func1() {cout << "Basisklasse" << endl;}
};
class Abgeleitet : public Basis {

190
Vererbung versus Einbettung

public:
void func2() {cout << "Abgeleitete Klasse" << endl;}
};

int main() {
Abgeleitet obj;
obj.func1();
obj.func2();

return 0;
}

Verweise
Siehe Zugriffsbeschränkung bei der Vererbung

Vererbung versus Einbettung


Beschreibung
Um in einer Klasse die Eigenschaften einer anderen Klasse nutzen zu können, gibt es – neben
der Möglichkeit der friend-Deklaration – zwei Möglichkeiten: die Vererbung und die Einbet-
tung.

Vererbung Einbettung
class X class X
{ {
... ...
}; };
class Y: public class X class Y
{ {
... class X var;
}; ...
};
Vererbung bringt Ihnen die Vorteile des Die Verwendung von Elementobjekten ist
Polymorphismus, der Zugriffsbeschnei- dagegen einfacher und besser zu über-
dungen und die Möglichkeit, Instanzen der schauen.
abgeleiteten Klasse wie Objekte der Basis-
klasse zu behandeln.

Tip
Sind Sie sich einmal unschlüssig, ob Sie die Funktionalität einer Klasse auf dem
Weg über die Vererbung oder durch die Deklaration eines Elementobjekts zur Ver-
fügung stellen, versuchen Sie sich klar zu machen, in welcher Beziehung die

191
Sprachkonzepte und Syntax

Objekte, die die Klassen repräsentieren, zueinander stehen. Stellen Sie sich einfach
die Frage:
»Kann man ein Objekt der Klasse Y auch als ein Objekt der Klasse X betrachten,
oder sieht es vielmehr so aus, daß zu einem Objekt der Klasse Y auch ein Objekt
der Klasse X gehört«
Auf einen kurzen Nenner gebracht, heißt das
» ist ein Y ein X «(Vererbung)
oder
» enthält Y ein X «(Einbettung)
Für drei Klassen Auto, Motor und Sportwagen würde dies beispielsweise bedeuten, daß
man die Klasse Sportwagen von der Klasse Auto ableiten würde (denn jeder Sportwa-
gen ist auch ein Auto). Dagegen enthält jedes Auto einen Motor, man würde also in
der Klasse Auto ein Objekt der Klasse Motor einbetten (und damit auch an die Klasse
Sportwagen vererben).

Verweise
Siehe Praxisteil, Kategorie Vererbung und Polymorphie

Zugriffsbeschränkung bei der Vererbung


public, protected, private

Beschreibung
Die Zugriffsspezifizierer public, protected und private können dazu benutzt werden, bei der
Vererbung die Zugriffsrechte der geerbten Elemente zu verändern.

Anwendung
Die folgende Tabelle zeigt wie sich die Zugriffsrechte für die geerbten Elemente bei
Verwendung der Zugriffsmodifizierer public, protected und private ändern. Die
Zugriffsspezifizierer der Vererbung regeln dabei nicht den Zugriff aus den Metho-
den der abgeleiteten Klassen auf die geerbten Elemente (dies wird schon durch die
Zugriffsspezifizierer in der Deklaration der Basisklasse geregelt). Die Zugriffsspezi-
fizierer der Vererbung betreffen nur die Zugriffsrechte, die die abgeleitete Klasse
für die geerbten Elemente nach außen weitergibt (beispielsweise, wenn über eine
Instanz der abgeleiteten Klasse auf diese Elemente zugegriffen wird, oder wenn die
abgeleitete Klasse selbst als Basisklasse benutzt wird). Ausgangsbasis sind die
Zugriffsrechte, die in der Basisklasse vorgesehen wurden. Diese können durch die
Zugriffsspezifizierer der Vererbung verschärft werden.

192
Zugriffsbeschränkung bei der Vererbung

Zugriffsspezifizierer der Vererbung Basisklasse abgeleitete Klasse


public public public
protected protected
private private
protected public protected
protected protected
private private
private public private
protected private
private private

Warnung
Wird kein Zugriffsspezifizierer angegeben, wird die Klasse private vererbt.

Beispiele
#include <iostream>
using namespace std;

class Basis {
int w_priv; // private
public:
int w_pub;
};

class Abgeleitet: private Basis {


public:
void func() {
w_priv = 2; // Zugriff verweigert, private-Element
w_pub = 2; // ok
}
};

int main() {
class Abgeleitet obj;

cout << obj.w_pub << endl; // Zugriff verweigert, private-Vererbung

return 0;
}

Verweise
Siehe Kategorie Klassen, Zugriffsspezifizierer
Siehe Zugriffsrechte für einzelne Elemente auflockern

193
Sprachkonzepte und Syntax

Zugriffsrechte für einzelne Elemente auflockern


Beschreibung
Zugriffsbeschränkungen durch die Vererbung können in der abgeleiteten Klasse explizit wieder
aufgelockert werden. Einer ererbten Eigenschaft kann jedoch nie eine weitreichendere Zugäng-
lichkeit zugewiesen werden, als sie in der Basisklasse aufweist.

Beispiele
class Basis {
int w_priv; // private
public:
int w_pub1;
int w_pub2;
int w_pub3;
};
class Abgeleitet: private Basis {
// Redeklaration der Zugriffsrechte
public:
Basis::w_pub1; // ist wieder public
using Basis::w_pub2; // ist wieder public
};

int main() {
class Abgeleitet obj;
cout << obj.w_pub1 << endl; // Zugriff auf geerbte Elemente
cout << obj.w_pub2 << endl;
cout << obj.w_pub3 << endl; // kein Zugriff
cout << obj.w_priv << endl; // kein Zugriff
...

Tip
Der neue ANSI-Standard empfiehlt die Redeklaration durch die using-Anweisung.

Verweise
Siehe Kategorie Klassen, Zugriffsspezifizierer

Vererbung und Konstruktor


Beschreibung
Konstruktoren und Destruktoren werden nicht vererbt. Daraus folgt, daß bei der Instanzbildung
einer abgeleiteten Klasse die ererbten Datenelemente vom Konstruktor der jeweiligen Basis-
klasse eingerichtet werden müssen. Tatsächlich bilden die von einer Basisklasse geerbten Ele-
mente in der abgeleiteten Klasse eine Art Unterobjekt mit eigenen Konstruktoren, Destruktoren,

194
Vererbung und Konstruktor

Zugriffsrechten, etc. Dieses Konzept ist die Grundlage für die in der objektorientierten Pro-
grammierung sehr gebräuchlichen Reduzierung eines abgeleiteten Objekts in ein Objekt einer
seiner Basisklassen.

Anwendung

Basisklassenobjekte einrichten Standardkonstruktor


Ist in der Basisklasse ein Standardkonstruktor vorhanden, braucht sich die abgelei-
tete Klasse überhaupt nicht um die Einrichtung und Initialisierung der geerbten Ele-
mente zu kümmern, sondern kann dies dem Compiler überlassen, der automatisch
im Zuge der Instanzbildung für Objekte der abgeleiteten Klasse den Standardkon-
struktor der Basisklasse aufruft.
class Basis {
public:
int b_wert;
Basis() { b_wert = 333;}
};
class Abgeleitet : public Basis {
public:
int abg_wert;
Abgeleitet(int i) { abg_wert = i;}
};

int main()
{
class Abgeleitet obj(11);

Basisklassenobjekte einrichten Spezieller Konstruktor


Um einen Konstruktor mit Argumenten für die Einrichtung der Basisklassenobjekte
aufzurufen, muß man eine Konstruktorliste anlegen.
Abgeleitet(int b1, double b2) : Basis1(b1), Basis(b2) { }
Die Konstruktorliste folgt mit einem Doppelpunkt auf den Namen des abgeleiteten
Konstruktors.
Um Argumente aus der Instanzbildung an einen Basisklassenkonstruktor weiterzu-
geben, muß für das jeweilige Argument im Konstruktor der abgeleiteten Klasse ein
Parameter für das Argument definiert werden.
class Basis {
public:
int b_wert;
Basis(int par) { b_wert = par;}
};
class Abgeleitet : public Basis {
public:

195
Sprachkonzepte und Syntax

int abg_wert;
Abgeleitet(int i) { abg_wert = i;}
Abgeleitet(int i, int n) : Basis(n) { abg_wert = i;}
};
int main()
{
class Abgeleitet obj(1,2);

Basisklassenobjekte einrichten Reinitialisierung


Schließlich kann man im Konstruktor der abgeleiteten Klasse den geerbten Elemen-
ten neue Werte zuweisen. Auf diese Weise kann man die durch die Basisklassen-
konstruktoren vorgesehene Initialisierung an die Bedürfnisse der abgeleiteten
Klasse anpassen oder den Code übersichtlicher gestalten. Beachten Sie aber, daß
● dies nichts daran ändert, daß die geerbten Elemente zuvor von einem Kon-
struktor ihrer eigenen Klasse eingerichtet werden,
● der Konstruktor der abgeleiteten Klasse im Gegensatz zum Konstruktor der
Basisklasse auf Elemente, die in der Basisklasse als private deklariert sind,
nicht zugreifen kann.
class Basis {
public:
int b_wert;
Basis() { b_wert = 333;}
};
class Abgeleitet : public Basis {
public:
int abg_wert;
Abgeleitet(int i) { abg_wert = i;
b_wert = 0;}
};

int main()
{
class Abgeleitet obj(11);

Mehrfachvererbung und Konstruktoren

Klassen mit mehreren direkten Basisklassen


Wird eine Klasse von mehreren direkten Basisklassen abgeleitet, beispielsweise
class B1 {...};
class B2 {...};
class A: public B1, public B2 {...};
werden deren Konstruktoren in der Reihenfolge ihrer Auflistung bei der Vererbung
abgearbeitet. Zuletzt wird der Anweisungsteil des Konstruktors der abgeleiteten
Klasse ausgeführt.

196
Nicht vererbbare Methoden

Klassen mit direkten und indirekten Basisklassen


Wird eine Klasse von einer Basisklasse abgeleitet, die selbst wieder von einer ande-
ren Klasse abgeleitet ist, beispielsweise
class B1 {...};
class B2: public B1 {...};
class A: public B2 {...};
wird zur Einrichtung des Basisklassenobjekts B2 der Konstruktor von B2 aufgerufen.
Da das B2-Objekt selbst wieder ein Basisklassenobjekt der Klasse B1 enthält, wird
als nächstes dessen Konstruktor aufgerufen und ausgeführt. Dann wird der Anwei-
sungsteil des B1-Konstruktors und zuletzt der Anweisungsteil des Konstruktors der
Klasse A ausgeführt.

Verweise
Siehe Kategorie Klassen, Der Konstruktor
Siehe Mehrfachvererbung

Nicht vererbbare Methoden


Nicht vererbbar sind:
● Konstruktor
● Destruktor
● Zuweisungsoperator
● Auch Friend-Deklarationen, die ehedem keine wirklichen Elemente darstellen,
werden nicht vererbt.

Polymorphie
Beschreibung
Der Begriff der Polymorphie ist eng an das Konzept der Vererbung gebunden. Er bezeichnet das
Phänomen, daß eine Methode in verschiedenen abgeleiteten Klassen einer Hierarchie unter-
schiedlich implementiert sein kann.

Anwendung
Auf diese Weise können einander ähnliche Klassen über eine Reihe gleichlautender
und gleichartig zu benutzender Funktionen verfügen, die es dem Programmierer
erlauben, Instanzen dieser Klassen gleich zu behandeln, ohne auf klassenspezifische

197
Sprachkonzepte und Syntax

Details, die in der Implementierung der Methoden versteckt sind (Information


hiding), zu achten.
Es liegt nahe, Methoden, die von mehreren Klassen benötigt werden, über eine
gemeinsame Basisklasse zu vererben. In den abgeleiteten Klassen werden die
Methoden überschrieben, um eine klassenspezifische Behandlung zu implementie-
ren. Methoden, die überschrieben werden sollen, werden üblicherweise in der
Basisklasse mit dem Schlüsselwort virtual deklariert.
Gelegentlich wird auch das Überladen von Funktionen und Operatoren als Poly-
morphie bezeichnet.

Beispiele
class ZeichenObjekt {
protected:
struct Punkt referenzpunkt;
virtual int zeichne(struct Punkt p) {
// zeichne Referenzpunkt an Koordinate p
...
}
};

class Rechteck : public ZeichenObjekt {


protected:
struct Punkt ecken[4];
virtual int zeichne(struct Punkt p) {
// zeichne Rechteck mit linker unterer Ecke in
// Koordinate p
...
};
};

class Kreis : public ZeichenObjekt {


protected:
float radius;
virtual int zeichne(struct Punkt p) {
// zeichne Kreis mit Mittelpunkt in Koordinate p
...
}
};

Verweise
Siehe Überschreibung und virtuelle Methoden
Siehe Basisklassenzeiger

198
Überschreibung und virtuelle Methoden

Überschreibung und virtuelle Methoden


Beschreibung
Überschreibung bedeutet im Gegensatz zum Überladen, daß es nur eine Implementierung der
Methode innerhalb einer Klasse gibt. (Die überschriebene Basisklassenversion kann allerdings
über den Namen der Basisklasse und den Gültigkeitsbereichoperator aufgerufen werden. Dies
wird häufig benutzt, um innerhalb der Implementierung der überschreibenden Methode die
Basisklassenversion aufzurufen.)

Anwendung
Der Compiler erkennt das Überschreiben einer Methode daran, daß neben dem
Methodennamen auch Anzahl und Typen der Parameter übereinstimmen. Über-
schriebene Methoden bzw. Methoden, die überschrieben werden sollen, werden in
der Basisklasse sowie in der abgeleiteten Klasse üblicherweise als virtual deklariert.
Das Schlüsselwort virtual modifiziert dabei die Art und Weise, in der der Compiler
eine Bindung zwischen einer Instanz und ihren Elementen herstellt..

Späte Bindung virtual


Das Schlüsselwort virtual ist notwendig, um die Namen von überschriebenen
Methoden in Klassenhierarchien richtig aufzulösen.
Das Problem der Namensauflösung entsteht überhaupt erst dadurch, daß ein
Objekt einer abgeleiteten Klasse praktisch auch ein Objekt der Basisklasse(n) ist.
Dieser Umstand macht es möglich, einem Zeiger oder einer Referenz vom Typ der
abgeleiteten Klasse die Adresse einer Instanz der Basisklasse zuzuweisen. Wird die-
ser Zeiger (oder die Referenz) nun dazu benutzt, eine Methode aufzurufen, die in
Basisklasse und abgeleiteter Klasse deklariert ist (wobei die abgeleitete Klasse die
Deklaration in der Basisklasse überschreibt), stellt sich die Frage, welche Version
aufgerufen werden soll:
● Die Methode der abgeleiteten Klasse, die dem Typ des Zeigers (der Referenz)
entspricht? Diese Art der Namensauflösung wird als frühe Bindung bezeich-
net, da sie zur Kompilierzeit vorgenommen wird.
Oder
● Die Version der Basisklasse, die dem Objekt entspricht, auf das der Zeiger (die
Referenz) verweist? Diese Art der Namensauflösung wird späte Bindung ge-
nannt, da sie erst zur Laufzeit erfolgt. Späte Bindung wird durch die Aufnah-
me des Schlüsselwortes virtual in die Funktionsdeklaration (zumindest der
Basisklassen-Version) vereinbart.

199
Sprachkonzepte und Syntax

Beispiele
#include <iostream>
using namespace std;

class Basis {
public:
virtual void identifziere()
{cout << "Dies ist die Basisklasse\n";};
};

class Abgeleitet : public Basis {


public:
virtual void identifziere()
{cout << "Dies ist die abgeleitete Klasse\n";};
};

int main() {
Abgeleitet abgeleitet_klasse;
Basis *zeiger = new Basis; // Zeiger vom Typ 'Zeiger auf Basis'

zeiger = &abgeleitet_klasse;
zeiger->identifiziere();
}
Ausgabe: »Dies ist die abgeleitete Klasse«

Warnung
● Für Klassen, die virtuelle Methoden enthalten (polymorphe Klassen) legt der
Compiler eine virtuelle Tabelle an, in der alle virtuellen Methoden eingetragen
sind. Zudem erhält die Klasse einen Zeiger auf ihre virtuelle Tabelle. Wird für
ein Objekt der Klasse eine virtuelle Methode aufgerufen, greift der Compiler
über diesen Zeiger auf die virtuelle Methode zu und entnimmt dieser die
korrekte Adresse für den Aufruf der virtuellen Methode. Auf diese Weise ist
sichergestellt, daß auch für Zeiger auf Klassenobjekte immer die zu dem Ob-
jekt passende Implementierung aufgerufen wird. Die späte Bindung erzeugt
damit zusätzlichen Objektcode und bedingt längere Laufzeiten.
● Konstruktoren können nicht als virtual deklariert werden.
● Statische Methoden können nicht als virtual deklariert werden.

Verweise
Siehe Vererbung und Destruktor

200
Vererbung und Destruktor

Vererbung und Destruktor


Beschreibung
Bei der Auflösung von Klassenobjekten wird automatisch der Destruktor aufgerufen. Dies ist
unter anderem auch der Fall, wenn für einen Zeiger auf ein Klassenobjekt der delete-Operator
aufgerufen wurde.
Dabei sollte sichergestellt sein, daß der Destruktor der Klasse aufgerufen wird, dem das Objekt
(und nicht der Zeiger, der auf das Objekt verweist) angehört.

Anwendung
Aus den vorangehenden Ausführungen zur späten Bindung und den oben aufge-
führten Gründen sollten Klassen, die Teil einer Vererbungshierarchie sind, über
einen virtuellen Destruktor verfügen.
Da der Destruktor, den der Compiler standardmäßig zuweist, nicht als virtual
deklariert ist, sollte man in Basisklassen von Klassenhierarchien einen eigenen vir-
tuellen Destruktor definieren, auch wenn man keinen Code in den Anweisungsteil
schreibt.

Beispiele
class Basis {
...
public:
virtual ~Basis() {}
};

Abstrakte Methoden und Klassen


Beschreibung
Abstrakte Methoden sind Methoden ohne Anweisungsteil, die erfordern, daß sie in abgeleiteten
Klassen überschrieben und mit einem Anweisungsteil versehen werden.

Abstrakte Methoden
Abstrakte oder "rein virtuelle" Methoden werden als virtual deklariert und auf 0
gesetzt. Sie dienen lediglich als Vorgabe einer Schnittstelle für abgeleitete Klassen
und haben keinen Definitionskörper. Sie müssen daher in den abgeleiteten Klassen
definiert werden.
virtual Typ name (PARAMETERLISTE) = 0;

201
Sprachkonzepte und Syntax

Abstrakte Klassen
Klassen, die über abstrakte Methoden verfügen, werden automatisch zu abstrakten
Klassen, mit der Konsequenz, daß von ihnen keine Instanz erzeugt werden kann.
Sie stehen in Klassenhierarchien stets ganz oben, um geeignete Schnittstellen vorzu-
geben und so der Hierarchie ein einheitliches Gepräge zu verleihen.

Warnung
Es ist zu beachten, daß Klassen, die von einer abstrakten Klasse abgeleitet wurden,
und für die es versäumt wurde, die abstrakten Methoden zu überschreiben (und
damit mit einem Definitionskörper zu versorgen), selbst zu abstrakten Klassen wer-
den.

Beispiele
class Basis {
public:
virtual void func() = 0;
...
};
class Abgeleitet: public Basis {
public:
virtual void func() { ... }
};

Basisklassenzeiger
Beschreibung
Da in einer abgeleiteten Klasse die Elemente der Basisklassen als Unterobjekte enthalten sind,
kann man ein abgeleitetes Objekt wie eines seiner Basisklassenobjekte behandeln, es quasi auf
sein Basisklassenunterobjekt reduzieren.
Insbesondere in Verbindung mit Basisklassenzeigern und virtuellen Methoden ist dies ein
äußerst nützliches Konzept, das in vielen Fällen äußerst effektive und elegante generische
Lösungen erlaubt.

Anwendung
Ein Basisklassenzeiger ist wie ein generischer Zeiger, dem man die Adressen abge-
leiteter Objekte zuweisen kann. (Unter der Voraussetzung, daß das Basisklassenun-
terobjekt in dem abgeleiteten Objekt eindeutig identifizierbar und zugänglich ist.)
Mit Hilfe dieser generischen Zeiger kann man

202
RTTI – Laufzeittypidentifizierung

● Objekte verschiedener abgeleiteter Klassen mit gemeinsamer Basisklasse in


einem Array (oder dynamischen Feld) verwalten,
class ZeichenObjekt { ... };
class Rechteck : public ZeichenObjekt { ... };
class Kreis : public ZeichenObjekt { ... };

int main() {
class ZeichenObjekt *geomFig[10];
geomFig[0] = new Kreis;
geomFig[1] = new Rechteck;
...
● generische Funktionen/Methoden implementieren, denen man Objekte ver-
schiedener abgeleiteter Klassen mit gemeinsamer Basisklasse als Argumente
übergeben kann.
void markieren(const ZeichenObjekt& objekt) { ... }

RTTI – Laufzeittypidentifizierung
Beschreibung
Um sinnvoll mit Basisklassenzeigern auf abgeleitete Objekte arbeiten zu können, muß es eine
Möglichkeit geben, wieder auf die volle Funktionalität des abgeleiteten Objekts zuzugreifen.
Das eigentliche Problem bei der Rückverwandlung ist die Typidentifizierung: welchem abgelei-
teten Klassentyp gehört das Objekt an, auf das der Basisklassenzeiger verweist.

Anwendung
Für die Typidentifizierung gibt es in C++ verschiedene Möglichkeiten:

Virtuelle Methoden Über einen Basisklassenzeiger soll für ein abgeleitetes Objekt eine in
der abgeleiteten Klasse überschriebene Methode aufgerufen werden.
base_ptr = &abg_obj;base_ptr->ueberschriebeneMethode();
Die Typidentifizierung erfolgt automatisch durch den Compiler.
Soweit möglich und sinnvoll sollte man diese Form der Typidentifi-
zierung nutzen.

203
Sprachkonzepte und Syntax

dynamic_cast Über einen Basisklassenzeiger soll für ein abgeleitetes Objekt eine in
der abgeleiteten Klasse neu definierte Methode oder ein neu definier-
tes Datenelement aufgerufen werden.

base_ptr = &abg_obj;
if(abg_ptr = dynamic_cast<Abgleitet *>(base_ptr)) {
abg_ptr->neueMethode();
abg_ptr->Datenelement();
}

Der Programmierer benutzt den dynamic_cast-Operator zur Um-


wandlung des Basisklassenzeigers in einen Zeiger auf Objekte einer
abgeleiteten Klasse und überläßt dem Operator die Aufgabe sicherzu-
stellen, daß diese Umwandlung korrekt ist. Wird in Fällen eingesetzt,
in denen man mit virtuellen Methoden nicht weiterkommt.
typeid Vergleicht zwei Datentypen, beispielsweise den Typ eines Objekts,
auf das ein Basisklassenzeiger verweist, mit dem Typ einer abgeleite-
ten Klasse.

base_ptr = &abg_obj;
if(typeid(*base_ptr) == typeid(Abgeleitet)) {
cout << "Objekt ist vom Typ Abgeleitet";
}

Der Operator dient lediglich der Typidentifizierung und wird meist


verwendet, wenn keine Rückverwandlung des Basisklassenzeigers er-
forderlich ist (sonst würde man möglichst den Operator
dynamic_cast verwenden). Sollte möglichst sparsam eingesetzt wer-
den. Den virtuellen Methoden und dem dynamic_cast-Operator ist –
wo möglich – der Vorzug zu geben.

Mehrfachvererbung
Beschreibung
Mehrfachvererbung bedeutet, daß eine Klasse mehr als eine direkte Basisklasse hat.
class Abgeleitet: public Basis1, public Basis2

Anwendung
Die Mehrfachvererbung ist interessant, wenn man ein Objekt einer abgeleiteten
Klasse als Objekt mehrerer Basisklassen verstehen kann oder, anders ausgedrückt,
wenn ein Objekt in sich die Eigenschaften mehrerer direkter Basisklassen vereinigt.
Ein typisches Beispiel wäre ein Amphibienfahrzeug, daß sowohl ein Auto als auch
ein Boot darstellt.

204
Virtuelle Basisklassen

Warnung: Namenskonflikte bei der Mehrfachvererbung


Bei der Mehrfachvererbung kann es schnell zu Namenskonflikten kommen, wenn
sich in den Basisklassen gleichlautende Elemente verbergen. Derartige Namenskon-
flikte können mit Hilfe des Bereichsoperators aufgelöst werden.

Beispiele
class Basis1 {
public:
void func();
};

class Basis2 {
public:
void func();
};

class Abgeleitet: public Basis1, public Basis2 {


...
};

int main() {
Abgeleitet abg;
[Link](); // Fehler
abg.Basis1::func(); // korrekt
...

Verweise
Siehe Virtuelle Basisklassen

Virtuelle Basisklassen
Beschreibung
Virtuelle Basisklassen sind Basisklassen, die mit dem Schlüsselwort virtual vererbt werden.
Für virtuelle Basisklassen stellt der Compiler sicher, daß die Elemente der Basisklassen in allen
abgeleiteten Klassen nie mehr als einmal auftauchen.

205
Sprachkonzepte und Syntax

Anwendung
Kreisschlüsse in der Vererbungshierarchie führen dazu, daß Elemente mehrmals
vererbt werden.

Das obige Vererbungsschema zeigt wie die Klasse Amphibienfahrzeug jeweils zwei
Vorkommen der Elemente max_geschw und get_geschw() der Basisklasse Fahrzeug
erbt: einmal auf dem Weg über die Klasse Boot und einmal über Auto. Dies kann in
bestimmten Klassenhierarchien sinnvoll sein (beispielsweise für das Amphibienfahr-
zeug, das als Boot und Auto unterschiedliche Maximalgeschwindigkeiten hat). Oft-
mals ist es jedoch unerwünscht. Man kann dies vermeiden, indem man die Basis-
klasse als virtual vererbt.

Beispiele
class Basis {
...
};
class Abgeleitet_1a : virtual public Basis {
...
};
class Abgeleitet_1b : virtual private Basis {
...
};
class Abgeleitet_2 : public Abgeleitet_1a, Abgeleitet_1b {
...
};

206
Templates

Warnung
Virtuell geerbte Elemente können nicht auf dem Weg über die direkten Basisklas-
senkonstruktoren eingerichtet werden. Statt dessen muß für virtuelle Basisklassen
ein entsprechender Konstruktor wie ein Basisklassenkonstruktor direkt in die Kon-
struktorliste aufgenommen werden. Der Programmierer steht damit vor den
gewohnten zwei Alternativen:
● Er kann die Initialisierung dem Standardkonstruktor der virtuellen Basisklasse
überlassen – falls ein Standardkonstruktor verfügbar ist.
● Er kann einen Konstruktor der virtuellen Basisklasse in die Konstruktorliste
aufnehmen.
class Fahrzeug
class Boot : virtual public Fahrzeug
class Auto : virtual public Fahrzeug
class Amphibienfahrzeug : public Boot, public Auto
{
public:
Amphibienfahrzeug(int preis) : Fahrzeug (preis) { }
};
Eine Basisklasse kann einer abgeleiteten Klasse gleichzeitig virtuell wie nicht-virtu-
ell vererbt werden.
● Jeder Pfad, über den die Basisklasse nicht-virtuell vererbt wird, erzeugt in der
abgeleiteten Klasse ein eigenes Basisklassenobjekt.
● Alle Pfade, über die die Basisklasse virtuell vererbt wird, erzeugen in der abge-
leiteten Klasse ein gemeinsames Basisklassenobjekt.

Templates

Templates
Beschreibung
Template bedeutet übersetzt Schablone. Templates sind vorgefertigte, typunabhängige Muster
für Klassen oder Funktionen. Wo immer in einer Klassen- oder Funktionsdeklaration ein Daten-
typ erforderlich ist, kann in der Template-Deklaration ein Platzhalter stehen. Diese Platzhalter
werden im Kopf der Template-Deklaration aufgelistet und bei der Instanzbildung durch die
gewünschten Typen ersetzt, woraufhin der Compiler eine entsprechende Instanz (Spezialisie-
rung) der Templateklasse erzeugt, d. h., eine Klassen- oder Funktionsdefinition erzeugt.

207
Sprachkonzepte und Syntax

Anwendung
Templates erinnern an Makros, sind diesen jedoch in puncto Vielseitigkeit und
Sicherheit überlegen. Compiler, die Templates unterstützen, haben daher meist die
üblichen C-Makros als Templates implementiert.
Templates werden oft mit Hilfe von überladenen Operatoren und Methoden imple-
mentiert, um einen typengerechten Einsatz dieser Funktionen / Operatoren inner-
halb der Template-Elementfunktionen zu gewähren.

Warnung
● Werden Platzhalter für Typen durch ein anderes Schlüsselwort als class oder
typename eingeführt, erwartet der Compiler für diesen Platzhalter eine entspre-
chende Konstante. Gleitkommatypen sind nicht zugelassen.
● Um in einer Quelltextdatei ein Template zu verwenden, das in einer anderen
Quelltextdatei des Programms definiert ist, müßten Sie im Prinzip die Templa-
te-Definiton über eine Header-Datei in die Quelltextdatei aufnehmen. Alterna-
tiv können Sie das Template auch mit dem Schlüsselwort export definieren.
Um das Template in anderen Quelltextdateien verwenden zu können, brau-
chen Sie dann nur noch die Template-Deklaration anzugeben.

Beispiele
// [Link]
export template<class T> int func(T a, T b) // Template-Definition
{
if (a == b)
return 1;
else
return 0;
}

// [Link]
template<class T> int func(T a, T b); // Template-Deklaration
int var1, var2;
...
func(var1, var2);

208
Funktionentemplates

Verweise
Siehe nachfolgende Abschnitte

Funktionentemplates
Beschreibung
Funktionentemplates sind typunabhängige Vorlagen für Funktionen, aus denen der Compiler
bei Bedarf durch Spezialisierung für vorgegebene Datentypen echte Funktionen erzeugen kann.

Anwendung
Funktionentemplates haben gegenüber der Überladung von Funktionen den Vor-
teil, daß der Anweisungsteil nur einmal aufgesetzt werden muß. (Voraussetzung ist
natürlich, daß die Anweisungen für alle Datentypen, für die das Template zu
instanziieren ist, gleich sind). Ansonsten kann man natürlich auch Funktionentem-
plates überladen.

Syntax
template <TYPENLISTE>
Rückgabetyp funktionsname(PARAMETERLISTE) { };
● TYPENLISTE: In der Typenliste werden durch Kommata getrennt, die später
zu ersetzenden Platzhalter aufgelistet. Jedem Platzhalter wird dabei das
Schlüsselwort class (oder typename) vorangestellt.
● Die weitere Deklaration folgt der Syntax zur Funktionsdeklaration, wobei
allerdings statt definierter Typen bereits die Platzhalter verwendet werden
können.

Beispiele
template<class T> T max(T a, T b) {
return a > b ?: a, b;
}
Instanziierung:
cout << max(3, -14) << endl;

Warnung
Durch mehrfache Instanziierung und Überladung kann es zu Uneindeutigkeiten
(ambiguities) kommen, d. h. der Compiler kann für einen Funktionsaufruf nicht
mehr entscheiden, welche Implementierung der Funktion aufzurufen ist.

209
Sprachkonzepte und Syntax

Verweise
Siehe Instanzbildung und Spezialisierung

Klassentemplates
Beschreibung
Klassentemplates sind typunabhängige Vorlagen für Klassen, aus denen der Compiler bei
Bedarf durch Spezialisierung für vorgegebene Datentypen echte Klassen erzeugen kann.

Anwendung
Das beste Beispiel für den Einsatz von Klassentemplates sind die Container der
Laufzeitbibliothek, die alle als Templates definiert sind. Dies erlaubt es, den Daten-
typ der Elemente, die im Container verwahrt werden sollen, als Template-Parame-
ter zu definieren. Der Container kann dann unabhängig vom Typ der Elemente
implementiert und bei Bedarf für die gewünschten Datentypen instanziiert werden.

Syntax
template <TYPENLISTE> class klassenname { };
● TYPENLISTE: In der Typenliste werden durch Kommata getrennt, die später
zu ersetzenden Platzhalter aufgelistet. Jedem Platzhalter ist dabei das Schlüs-
selwort class (oder typename) vorangestellt.

Warnung
● Methoden innerhalb von Klassentemplates sind automatisch Funktionentem-
plates, d. h., sie können die Platzhalter des Klassentemplates gebrauchen, ohne
daß eine explizite Template-Deklaration für diese Platzhalter erforderlich ist.
● Friend-Funktionen, die in Klassentemplates deklariert werden, sind nicht au-
tomatisch Funktionentemplates, d. h., standardmäßig sind solche Funktionen
Friends zu allen typisierten Klassen, die aus dem Template gebildet werden.
Erst wenn eine friend-Funktion in ihrer Deklaration einen Platzhalter des
Klassentemplates enthält, gibt es für jede typisierte Klasse eine eigene friend-
Funktion. Man kann friend-Funktionen auch als spezialisierte Templates
deklarieren, um so anzuzeigen, daß die friend-Deklaration nur für die angege-
benen Spezialisierungen des Templates gelten.
● Friend-Templates dürfen nicht im Template definiert werden.
● Werden in einem Template statische Elemente definiert, erhält jede Spezialisie-
rung des Templates seinen eigenen Satz von statischen Elementen.

210
Methoden in Klassentemplates

● Templates können sowohl von Templates als auch von normalen Klassen ab-
geleitet werden und können wiederum ihrerseits als Basisklasse für andere
Templates oder Klassen verwendet werden.
● Benutzerdefinierte Namen in Template-Deklarationen werden standardmäßig
als Bezeichner für Variablen aufgefaßt. Damit ein Name als Typbezeichner er-
kannt wird, muß der Name innerhalb des Templates oder im umgebenden
Gültigkeitsbereich definiert worden sein oder durch das Schlüsselwort typename
gekennzeichnet werden.
● Template-Klassenelemente können nicht als virtual deklariert werden.
● Lokale Klassen dürfen keine Template-Klassenelemente enthalten.

Beispiele
template <class T> class demo {
T var;
public:
demo() { var = 1.5;}
T func() { T tmp;
tmp=var++;
return tmp;
};
};
Instanziierung:
demo<double> obj;

Verweise
Siehe Instanzbildung und Spezialisierung

Methoden in Klassentemplates
Beschreibung
Methoden von Klassentemplates sind automatisch Funktionentemplates, d. h., sie können die
Platzhalter des Klassentemplates gebrauchen, ohne daß eine explizite Template-Deklaration
für diese Platzhalter erforderlich ist. Innerhalb des Templates unterscheidet sich ihre Syntax
praktisch nicht von Methoden gewöhnlicher Klassen. Außerhalb des Klassentemplates, zum
Beispiel zur ausgelagerten Definition, müssen sie als Element ihres Klassentemplates gekenn-
zeichnet sein:

211
Sprachkonzepte und Syntax

Syntax
template <TYPENLISTE> Rückgabetyp
klassenname<TYPENLISTE>::funkt_name(PARAMETERLISTE)
{ };

Warnung
Gemäß dem neuen ANSI-C++-Standard können innerhalb von Klassentemplates
auch Funktionentemplates mit eigenen Platzhaltern deklariert werden. Dieses Kon-
zept ist allerdings recht schwierig zu implementieren und wird nicht von allen
Compilern unterstützt.
Methoden von Klassentemplates müssen prinzipiell in der gleichen Datei definiert
werden wie das Klassentemplate. Um beide Teile zu trennen, muß man da Schlüs-
selworte verwenden (siehe Einleitung zu Templates).

Beispiele
template<class T, class S> class demo {
T var1;
S var2;
public:
T func();
};

template<class T, class S> T demo<T,S>::func() {


return var1;
}

Verweise
Siehe Klassentemplates

Instanziierung und Spezialisierung


Beschreibung
Ein Template ist lediglich eine Schablone, eine Vorlage für später zu erstellende Funktionen
oder Klassen. Der nächste Schritt nach der Definition eines Templates besteht also darin, auf
der Grundlage des Templates eine oder mehrere Funktionen (oder Klassen) zu erzeugen, mit
denen man arbeiten kann. Die grundsätzliche Vorgehensweise dabei ist, dem Compiler anzuge-
ben, welche konkreten Datentypen er für die Platzhalter des Templates verwenden soll, und
diesem dann die Aufgabe zu überlassen, aus dem typunabhängigen Template und den spezifi-
zierten Datentypen eine echte Funktion oder Klasse zu generieren.
Die Funktionen oder Klassen, die auf der Grundlage eines Templates erzeugt werden, bezeich-
net man als Spezialisierungen.

212
Implizite Instanziierung

Anwendung
Um dem Compiler anzuzeigen, daß er für einen bestimmten Satz von Datentypen
aus einem Template eine Spezialisierung erzeugen soll, gibt es drei Möglichkeiten:
● Implizite Instanziierung
● Explizite Instanziierung
● Explizite Spezialisierung

Verweise
Siehe nachfolgende Abschnitte

Implizite Instanziierung
Beschreibung
Bei der impliziten Instanzbildung überläßt der Programmierer fast die gesamte Arbeit dem
Compiler. Der Programmierer muß lediglich dafür Sorge tragen, daß der Compiler alle Informa-
tionen hat, um den Platzhaltern des Templates konkrete Datentypen zuweisen zu können.

Anwendung
Für Funktionentemplates genügt es meist, die Funktion mit entsprechenden Argu-
menten aufzurufen. Der Compiler entnimmt die Typinformation dann den Argu-
menten.
Typen für Klassen oder Rückgabewerte von Funktionen können nicht auf diese
Weise abgeleitet werden. In so einem Fall muß man die Typen für die Platzhalter in
spitzen Klammern explizit angeben.

Implizite Instanziierung für Funktionentemplates


template <class T1, class T2> void demo_func(T1 a, T2 b) {
...
}

int main() {
demo_func(13,14);
demo_func<int>(13.2,14.3);
return 0;
}

Erläuterung
demo_func(13,14);

213
Sprachkonzepte und Syntax

Der Compiler erkennt, daß eine Spezialisierung des Templates demo_func benötigt
wird. Anhand der Typen der Aufrufargumente kann er die gewünschten Typen für
die Platzhalter T1 und T2 bestimmen. Der Compiler erzeugt also eine Spezialisie-
rung demo_func<int, int> und ruft diese mit den Argumenten (13,14) auf
demo_func<int>(13.2,14.3);
Der Compiler erkennt, daß eine weitere Spezialisierung des Templates demo_func
benötigt wird. Den Typ für den ersten Platzhalter T1 entnimmt er den Templatear-
gumenten, die in spitzen Klammern übergeben wurden. Den Typ für den zweiten
Platzhalter T2 entnimmt er dem Typ des zugehörigen Aufrufarguments. Der Com-
piler erzeugt also eine Spezialisierung demo_func<int, double> und ruft diese mit den
Argumenten (13.2,14.3) auf.

Warnung
Bei der Instanziierung von Funktionen aus Funktionentemplates berücksichtigt der
Compiler keine Standardkonvertierungen. Wenn ein Funktiontemplate zwei Para-
meter des gleichen Platzhaltertyps definiert, kann man das Template nicht instanzi-
ieren, indem man ihm zwei Argumente unterschiedlicher Typen übergibt – auch
wenn diese durch Standardkonvertierungen ineinander umwandelbar sind.
Eine einmal erzeugte Spezialisierung eines Funktionentemplates kann wie jede
Funktion mit konvertierbaren Argumenten aufgerufen werden.

Implizite Instanziierung für Klassentemplates


Bei der Instanziierung von Klassentemplates müssen die Datentypen für die Platz-
halter immer vollständig angegeben werden:
template<class T> class demo_class {
T var;
public:
T func() { return var; }
};

int main() {
demo_class<int> obj; // implizite Instanziierung
return 0;
}

Verweise
Siehe explizite Instanziierung und Spezialisierung

214
Explizite Instanziierung

Explizite Instanziierung
Die explizite Instanziierung ist eine Aufforderung an den Compiler, die gewünschte
Spezialisierung des Templates sofort zu erzeugen, auch wenn diese Spezialisierung
noch gar nicht benötigt wird.
Eingeleitet wird die explizite Instanziierung durch das Schlüsselwort template. Die
Argumente für die Templateparameter werden allerdings nicht an das Schlüssel-
wort template, sondern an den Namen der Funktion oder Klasse angehängt (dies
dient der Unterscheidung zur expliziten Spezialisierung).

Explizite Instanziierung für Funktionentemplates


template <class T1, class T2> void demo_func(T1 a, T2 b) {
cout << a << " " << b <<endl;
}

// Explizite Instanziierung
template void demo_func(int, int);
template void demo_func<int, double>(int, double);

int main() {
demo_func(13,14);
demo_func<int>(13.2,14.3);
...

Explizite Instanziierung für Klassentemplates


Bei der Instanziierung von Klassentemplates müssen die Datentypen für die Platz-
halter immer vollständig angegeben werden:
template<class T> class demo_class {
T var;
public:
T func() { var = 1; return var; }
};

template class demo_class<int>;

int main() {
demo_class<int> obj;
...

Verweise
Siehe implizite Instanziierung und Spezialisierung

215
Sprachkonzepte und Syntax

Explizite Spezialisierung
Beschreibung
Während wir unter einer Spezialisierung einfach eine konkrete Funktion oder Klasse verstehen,
die auf der Basis eines Templates generiert wurde, sprechen wir von expliziter Spezialisierung,
wenn
● einzelne oder alle Platzhalter eines Templates durch konkrete Datentypen er-
setzt werden, und wenn
● für dieses stärker typabhängige Template eine eigene Definition vorgesehen
wird.

Syntax
Die Syntax der Spezialisierung erfordert zwei Templateparameterlisten in spitzen
Klammern:
template <erste_Liste> Name <zweite_Liste>
● In der ersten Liste, die auf das Schlüsselwort template folgt, werden die Tem-
plateparameter aufgeführt, die in der Spezialisierung noch weiter verwendet
werden.
● In der zweiten Liste, die auf den Namen der Spezialisierung folgt, werden Ar-
gumente für die Templateparameter des primären Templates übergeben.
Diese Syntax erlaubt auch die partielle Spezialisierung:
template <class T1, class T2> class demo {...};
template <class T> class demo<T, char> {...};
template <class T> class demo<T*, T> {...};
template <> class demo<int, int> {...};
Die erste Zeile enthält die Definition des primären Templates.
Darunter folgen zwei partielle Spezialisierungen, die nur noch einen Platzhalter ver-
wenden. In der Templateargumentenliste wird festgelegt, welche Datentypen oder
Platzhalter mit den Platzhaltern des primären Templates korrespondieren.
Die letzte Zeile definiert eine vollständige explizite Spezialisierung.

Warnung
● Explizite Spezialisierungen haben stets Vorrang vor impliziten oder expliziten
Instanziierungen.
● Eine explizite Instanzbildung oder Spezialisierung muß im gleichen Namensbe-
reich (namespace) erfolgen wie das zu spezialisierende Template.
● Für Klassentemplates kann man auch einzelne Methoden explizit spezialisie-
ren.

216
Explizite Spezialisierung

Die obige Syntax mit dem vorangehenden Schlüsselwort template und der nachfol-
genden Templateparameterliste ist noch recht neu. Die meisten Compiler erlauben
Spezialisierungen nur in Form einer vereinfachten Syntax ohne das Schlüsselwort
template:
// aeltere Form der Spezialisierung
int vergleich<char*>(char *a, char *b) {
return(strcmp(a,b));
}

Beispiele
// Funktionentemplate
template <class T> int vergleich(T a, T b) {
cout << "Erstes Template:\t";
return(a > b);
}

// Spezialisierung für Datentyp char *


template <> int vergleich<char*>(char *a, char *b) {
return(strcmp(a,b));
}

Verweise
Siehe implizite und explizite Instanziierung

Der Präprozessor
Beschreibung
Neben der reinen Sprachdefinition beschreibt der ANSI-C-Standard unter anderem auch die
Phasen, die erfolgen müssen, damit der Sourcecode eines Programms in den von der Maschine
ausführbaren Code übersetzt werden kann. Eines der beim Übersetzungsvorgang beteiligten
Programme ist der sogenannte Präprozessor, der – der Name läßt es bereits vermuten – vorbe-
reitende Arbeiten an dem Quellcode durchführt. (In neueren Compilern ist das Präprozessing
kein getrennter Prozeß mehr, sondern wird beim Kompilieren mit ausgeführt.) Erst nachdem
der Präprozessor den Code bearbeitet hat, wird er zur eigentlichen Code-Generierung an den
Compiler weitergeleitet.

Anwendung
Der Präprozessor führt neben einfachen Quelltextersetzungen, die automatisch
ablaufen, weitere Aufgaben aus:
● Kommentare werden entfernt (und durch Leerzeichen ersetzt).
● Zeilenumbrüche, denen ein Backslash vorangeht, werden entfernt.

217
Sprachkonzepte und Syntax

● Aufeinanderfolgende String-Literale werden zusammengefaßt (konkateniert).


● Whitespace-Zeichen zwischen Tokens werden gelöscht. (Ein Token ist ein Be-
zeichner, der im Programm syntaktische Bedeutung hat.)
● Trigraph-Sequenzen werden ersetzt.
auch einige ausgeklügeltere Ersetzungen, die vom Programmierer gesteuert werden
können. Diese Ersetzungen werden mit Hilfe bestimmter Präprozessor-Direktiven
explizit im Quelltext definiert. Mit ihrer Hilfe kann der Programmierer
● Header- und Quelldateien in den Quelltext kopieren lassen (#include),
● symbolische Konstanten einführen (#define),
● über »Schalter« steuern, welche Code-Abschnitte übersetzt werden sollen (be-
dingte Kompilierung mit #ifdef, etc.).
Die Anweisungen an den Präprozessor beginnen immer mit dem Zeichen »#« und
stehen immer allein in einer Zeile.
Die nachfolgende Tabelle enthält eine Übersicht über Präprozessor-Direktiven und
-Operatoren, die der ANSI-Standard vorschreibt.

Direktive Bedeutung
defined Operator, der testet, ob ein Makro definiert ist
# Operator zur Zeichenkettenbildung
## Operator zur Grundsymbolverbindung
#define definiert ein Symbol oder Makro
#elif else-if-Operator
#else else-Operator
#endif Ende der #if-Direktive
#error erzeugt eine Fehlermeldung
#if if-Operator
#ifdef Äquivalent zu #if defined
#ifndef Äquivalent zu #if !defined
#include Datei einbinden
#line Aktuelle Zeile verändern
#pragma Anweisung für den Compiler
#undef Definition eines Symbols entfernen

218
Quellcode einfügen und ersetzen

Quellcode einfügen und ersetzen


#include

Beschreibung
Die für den Programmierer wichtigste Direktive an den Präprozessor ist sicherlich die Direktive
#include. Mit ihr wird der Präprozessor angewiesen, die als Argument angegebene Datei in die
aktuelle Datei einzukopieren.

Anwendung
Meist wird hiermit eine sogenannte Header-Datei aufgenommen, die Deklaratio-
nen, symbolische Konstanten, Makros und/oder Typdefinitionen enthalten kann.
Das Einbinden der Datei kann an jeder beliebigen Stelle der Sourcedatei erfolgen.
Es existiert jedoch eine stillschweigende Übereinkunft darüber, daß das Einbinden
am Anfang der Datei stattfindet.
Die Verwendung von Header-Dateien empfiehlt sich besonders für Programme, die
aus mehreren Quelltextdateien bestehen. Die gemeinsam benutzbaren Typdefinitio-
nen, Konstanten, Funktionsdeklarationen können auf diese Weise durch eine ein-
zeilige Anweisung allen beteiligten Dateien bekanntgemacht werden.

Syntax
Zwei verschiedene Formen der #include-Direktive sind möglich:
#include <datei>
Der Compiler sucht nach der angegebenen Datei in bestimmten in der Entwick-
lungsumgebung des Compilers spezifizierten Verzeichnissen.
#include "datei"
Der Compiler sucht nach der angegebenen Datei in einer compilerspezifischen Rei-
henfolge. Üblicherweise wird zuerst im aktuellen Verzeichnis gesucht.

Beispiele
#include <stdio.h>
#include "Unterverzeichnis\typen.h"

Verweise
Siehe Grundlagenteil, Verwendung der Standardbibliotheken

219
Sprachkonzepte und Syntax

Makros definieren
#define makroname

Beschreibung
Mit der Präprozessor-Direktive #define wird die Definition eines Makros eingeleitet.

Anwendung
Eine Makrodefinition besitzt die folgende Form:
#define makroname neuer_text
Der Präprozessor ersetzt, nachdem er die Makrodefinition zur Kenntnis genommen
hat, jedes Vorkommen von makroname mit neuer_text.
Der Name eines Makros wird nach den gleichen Regeln wie ein Variablenname
gebildet. Es hat sich jedoch eingebürgert, Makronamen in Großbuchstaben zu
schreiben. Diese Nomenklatur – wird sie konsequent eingehalten – macht auf den
ersten Blick deutlich, ob es sich um einen Variablen-/Funktionsnamen oder ein
Makro handelt.

Warnung
Die Festlegung des Ersatztextes hört am Ende der Zeile auf. Um auch Makros
schreiben zu können, die sehr lang und komplex sind, ist es möglich, vor der Zei-
lenschaltung das Zeichen Backslash »\« einzufügen und die Definition des Makros
auf der bzw. den folgenden Zeilen fortzuführen.
Wird kein Ersatztext angegeben, wird nur der Makroname eingeführt, der als eine
Art Compiler-Schalter bei der bedingten Kompilierung eingesetzt werden (und
jederzeit mit #undef makroname wieder entfernt werden) kann.

Beispiele
#define GROESSE 20
int feld[GROESSE];
...
for (int i = 0; i < GROESSE; i++) { ...

Verweise
Siehe Argumente in Makros
Siehe Direktiven zur bedingten Kompilierung
Siehe Kategorie Konstanten, #define

220
Argumente in Makros

Argumente in Makros
#define name()

Beschreibung
Es ist auch möglich, in Makros Argumente zu verwenden, innerhalb des Makros mit den Argu-
menten zu arbeiten und das gleiche Makro für verschiedene Argumente zu verwenden.

Anwendung
Auf diese Weise können Funktionen durch Makroaufrufe ersetzt werden, wodurch
der leidige Function Overhead vermieden und typunabhängige Implementierungen
möglich werden.

Warnung
Die Übergabe von Argumenten führt aber schnell zu unerwünschten Nebeneffek-
ten, so daß in C++ der Deklaration von inline-Funktionen zur Vermeidung des
Function Overheads beziehungsweise die Programmierung von überladenen und
Operatoren sowie von Templates zur Erreichung typunabhängiger Implementierun-
gen der Vorzug zu geben ist.

Beispiele
#define flaeche(a,b) (a*b) // falsch
ergebnis = flaeche(4,6); // liefert 24
ergebnis = flaeche(3+1,5+1); // liefert 9!

Erläuterung
Das falsche Ergebnis resultiert aus der falschen Definition des Makros. Der Präpro-
zessor ersetzt die zweite Zuweisung durch
ergebnis = 3+1*5+1
und dies führt zu dem falschen Ergebnis, da die Multiplikation die höhere Priorität
hat.
Alle Argumente, die in einer Makrodefinition vorkommen, sollten daher geklam-
mert werden, um diese Nebeneffekte, die manchmal schwer zu finden sind, zu ver-
meiden.
Richtig wäre:
#define flaeche(a,b) ((a)*(b)) /* so ist's richtig */

Verweise
Siehe Kategorie Templates, Funktionentemplates

221
Sprachkonzepte und Syntax

Direktiven zur bedingten Kompilierung


Beschreibung
Mit den Direktiven zur bedingten Kompilierung können verschiedene Bereiche einer Datei
wahlweise kompiliert oder von der Kompilation ausgeschlossen werden.

Anwendung
Mit Hilfe der bedingten Kompilierung kann man beispielsweise verschiedene Ver-
sionen eines Programms aufbauen. Diese Versionen können sein:
● eine Version, die Debugging-Code enthält,
● Programme, die auf unterschiedlicher Hardware laufen oder
● Versionen, die mit unterschiedlichen Compilern arbeiten sollen.
Die Direktiven zur bedingten Kompilierung werten einen Makronamen aus, um zu
ermitteln, welche Bereiche der Quelldatei vom Präprozessor an den Compiler wei-
tergeleitet bzw. aus dem Sourcecode ausgeschlossen werden sollen.
Der Anweisungsblock zur bedingten Kompilierung umfaßt mehrere Zeilen:
● Die Zeile, in der die zu testende Bedingung steht. Sie wird mit #if, #ifdef oder
#ifndef eingeleitet.
● Zeilen, die den Code beinhalten, wenn die auszuwertende Bedingung den Wert
wahr ergibt (optional).
● Eine optionale else-Zeile, die mit #else oder #elif eingeleitet wird.
● Zeilen, die den Code beinhalten, wenn die auszuwertende Bedingung den Wert
unwahr ergibt (optional).
● Eine Zeile, mit der der Block zur bedingten Kompilierung abgeschlossen wird:
die #endif-Anweisung.

#if
Die Präprozessor-Direktive #if leitet die bedingte Kompilierung ein. Danach steht
ein konstanter Ausdruck, der ausgewertet wird. Ergibt die Auswertung wahr, wird
der nachfolgende Teil (entweder bis zum nächsten #elif, #else oder #endif) an den
Compiler weitergeleitet.

#elif
Die Direktive #elif ist eine Abkürzung für else if. Dieser Ausdruck wird nur dann
ausgewertet, wenn die Auswertung der vorhergehenden Direktive das Resultat
unwahr erbrachte. #elif kann in einem Block zur bedingten Kompilierung mehr-
mals vorkommen. Ergibt die Auswertung wahr, wird der nachfolgende Teil (entwe-
der bis zum nächsten #elif, #else oder #endif) an den Compiler weitergeleitet.

222
Direktiven zur bedingten Kompilierung

#else
#else kann in einem Anweisungsblock nur einmal vorkommen. Die hinter #else ste-
henden Anweisungen werden bis zum abschließenden #endif an den Compiler wei-
tergeleitet, wenn keine der vorhergehenden Auswertungen das Ergebnis wahr
erbrachte.

Ende des bedingten Kompilierblocks #endif


Die Präprozessordirektive #endif muß für jedes #if, #ifdef und #ifndef verwendet
werden, um das Ende des Blockes zur bedingten Kompilierung anzuzeigen.

Bedingte Kompilierung und Makrodefinition #ifdef, #ifndef


Bei den Direktiven #ifdef und #ifndef handelt es sich um die alte Form der Direkti-
ven zur bedingten Kompilierung. Mit ihnen kann nur getestet werden, ob der als
Argument angegebene Bezeichner definiert ist oder nicht.
Mit #if defined bzw. #if !defined ist es darüber hinaus möglich, den zurückgelie-
ferten Wert zu verknüpfen, was mit #ifdef und #ifndef nicht möglich ist.
#ifdef bezeichner
#ifndef bezeichner

Der Operator defined


Der Präprozessor-Operator defined liefert den Wert wahr (entspricht 1) zurück,
wenn der als Argument angegebene Bezeichner zuvor mit #define definiert wurde.
Ist der Bezeichner nicht definiert, gibt der Operator den Wert unwahr (entspricht
0) zurück.
Die beiden folgenden Anweisungen sind identisch:
#if defined MAXZEILEN
#ifdef MAXZEILEN

Beispiele
#if defined(ZIELSYSTEM) && (MAXSPALTEN==80)
#define ARRAY_GROESSE 160
#elif !defined(ZIELSYSTEM)
#define ERROR1
#error Datei kann nicht kompiliert werden.
#endif

223
Sprachkonzepte und Syntax

Zeichenkettenbildung und
Grundsymbolverbindung
Zeichenkettenbildung #
Der Operator zur Zeichenkettenbildung (string-izing operator) wird bei funktions-
ähnlichen Makros benutzt. Er bewirkt, daß ein dem Makro übergebenes Argument
in eine Zeichenkette umgewandelt wird.
#define makestring(s) printf(#s "\n")
int main() {
makestring(Dies wird ein String);
makestring("Dies wird noch ein String");
...
wird vom Präprozessor umgesetzt zu:
int main() {
printf("Dies wird ein String" "\n");
printf("\"Dies wird noch ein String\"" "\n");
...
Die Ausgabe des Programms:
Dies wird ein String
"Dies wird noch ein String"

Grundsymbolverbindung ##
Mit dem Operator zur Grundsymbolverbindung (token-pasting operator) können
einzelne Token zu einem Grundsymbol verknüpft werden. Der Operator »##«
sowie alle zwischen den Token stehenden Zwischenraumzeichen werden vom Prä-
prozessor entfernt.
#define zeigevar(zahl) printf("%d\n", var ## zahl)
int main() {
int var3=3;
zeigevar(3);
...
wird vom Präprozessor umgesetzt zu:
int main() {
int var3=3;
printf("%d\n", var3);
return 0;
}

224
Sonstige Direktiven und Symbole

Sonstige Direktiven und Symbole


Diagnosemeldungen #error
Mit der Verwendung der Präprozessor-Direktive #error erreichen Sie, daß der Com-
piler den (optionalen) Text auf dem stderr-Gerät ausgibt und anschließend die
Kompilierung abbricht. Der Text braucht nicht in Anführungszeichen eingeschlos-
sen zu werden.
#error <text>

Beispiele
#if !defined AUTO && !defined FAHRRAD
#error Definieren Sie das gewünschte Transportmittel
#endif
Das vorstehende Beispiel könnte aus einem Programm stammen, bei dem über die
bedingte Kompilierung, je nach gewünschtem Transportmittel, anderer Code
erzeugt wird. Da das Programm nur einwandfrei kompiliert werden kann, wenn
entweder AUTO oder FAHRRAD definiert ist, wird mit dem defined-Operator
getestet, ob die Definition existiert. Ist dies nicht der Fall, wird der hinter #error
stehende Text ausgegeben.

Zeilen-Steuerdirektive1 #line
Mit der Zeilen-Steuerdirektive #line kann die Zeilennummer innerhalb einer Datei
eingestellt und der Name der Datei geändert werden. Diese Daten werden vom
Compiler benutzt, um auf eventuelle Fehler zu verweisen.
Durch die Verwendung von #line werden die Werte in den Symbolen __LINE__ und
__FILE__ geändert.
Diese Direktive wird üblicherweise von Programmgeneratoren benutzt, um Fehler
in dem erzeugten C-Code mit der Zeile und dem Dateinamen der Ursprungsdatei
zu verknüpfen.
#line <Zeile> ["dateiname"]
● Zeile: Eine Ganzzahlkonstante, auf die der interne Zähler des Compilers ge-
setzt wird.
● dateiname: Dieses Argument ist optional und kann einen in Anführungszei-
chen eingeschlossenen Dateinamen enthalten.

Beispiele
#line 200
#line 200 "ursprung.c"

225
Sprachkonzepte und Syntax

Pragma-Direktiven #pragma
Die #pragma-Direktive ist eine compilerspezifische Direktive, d. h., die Verarbeitung
der Direktive hängt nicht vom ANSI-Standard, sondern vom verwendeten Compi-
ler ab.
Pragma-Direktiven, die nicht zur Implementierung gehören, werden ignoriert. Da
dies stillschweigend geschieht, muß bei der Portierung von Code auf eine andere
Implementierung mit anderen Pragmas besonders sorgfältig vorgegangen werden.

Vordefinierte Symbole und Konstanten


Nach ANSI C/C++ sind sechs verschiedene Konstanten vordefiniert.

Makro Bedeutung
__DATE__ Datum der Kompilierung der Datei
__FILE__ Name der Sourcedatei
__LINE__ Aktuelle Zeile in der Sourcedatei
__STDC__ Compiler entspricht ANSI-C-Standard
__TIME__ Zeit der Kompilierung der Datei
__cplusplus C++ -Code

Exception-Behandlung

Exception-Behandlung
Beschreibung
Unter Exception-Behandlung versteht man eine mit C++ in die Sprache eingeführte Form der
Fehlerbehandlung. Die Exception-Behandlung ist nicht auf Klassen oder andere Konzepte der
objektorientierten Programmierung angewiesen, arbeitet mit diesen aber besonders effektiv
zusammen:

Vorteile der Exception-Behandlung


So erlaubt die Exception-Behandlung eine räumliche Trennung von Fehlerauslöser
und Fehlerbehandlung. Eine Bibliotheksfunktion braucht ihre Fehler also nicht
selbst zu verarbeiten. Statt dessen löst sie eine Exception aus und überläßt die
Behandlung des Fehlers dem aufrufenden Programm.

226
Exception-Behandlung

Der zweite Vorteil liegt darin, daß die Weiterreichung der Exception nicht über den
Rückgabetyp, die Parameter oder irgendwelche globale Variablen erfolgt. Die für
den korrekten Einsatz der Funktion benötigte Schnittstelle wird also nicht belastet
oder aufgebläht. Dies ist besonders wichtig für Elemente wie zum Beispiel Kon-
struktoren, die keine Werte zurückliefern können.
Da Exceptions Objekte eines bestimmten Datentyps sind, können Sie Informa-
tionen vom Ort des Fehlers zum Ort der Fehlerbehandlung übertragen.
Viertens wird der Quellcode übersichtlicher, da der eigentliche Algorithmus und
die Fehlerbehandlung getrennt ablaufen.

Nachteile der Exception-Behandlung


Exceptions sollten nur für schwerwiegende Fehler verwendet werden, die nicht
anders behoben werden können. Unbehandelte Exceptions führen, sofern vom Pro-
grammierer keine andere Exception-Behandlung vorgesehen wurde, zum Pro-
grammabbruch. Gerade Entwickler von Bibliotheken sollten daher vermeiden, für
jede kleine Unstimmigkeit eine Exception auszulösen, die die Benutzer der Biblio-
thek dann abfangen müssen.
Exceptions, die nicht in der gleichen Funktion abgefangen werden, in der sie ausge-
löst wurden, führen zur Auflösung des Stacks, d. h. die auf dem Stack befindlichen
Funktionen werden, ohne zu Ende ausgeführt zu werden, vom Stack entfernt. Dies
wiederum kann zu Problemen führen, wenn Ressourcen, die von den Funktionen
angefordert wurden, nicht mehr wie am Ende der Funktion freigegeben werden
(beispielsweise Freigabe dynamisch reservierten Speichers).

227
Sprachkonzepte und Syntax

Prinzipiell gibt es zwei Möglichkeiten, diesem Problem zu begegnen:


● Die eine Möglichkeit besteht darin, vorsorglich alle Exceptions in der Funk-
tion abzufangen, dann die Ressourcen freizugeben und die Exceptions schließ-
lich erneut auszuwerfen:
void func() {
FILE *fp = fopen("[Link]","rt");
try {
func_that_may_throw(fp);
}
catch(...) { // ... fängt alle Exceptions
fclose(fp);
throw; // Exceptions weiterleiten
}
fclose(fp);
}
● Die andere Möglichkeit besteht darin, die Ressource in einer lokalen Klassen-
instanz zu kapseln. Deren Destruktor wird auf jeden Fall zur Auflösung der
Klasseninstanz aufgerufen und der Programmierer kann in der Implementie-
rung des Destruktors sicherstellen, daß die Ressource freigegeben wird.

Schema einer Exception-Behandlung


● Eine Exception-Behandlung beginnt mit dem Auftreten eines Fehlers, beispiels-
weise einer Division durch Null.
● Als Antwort auf den Fehler löst die Funktion, in der der Fehler auftrat, eine
Exception aus. Eine Exception ist eine Instanz eines Datentyps. Die Instanz er-
hält üblicherweise Informationen über den aufgetretenen Fehler. Eine einfache
Exception wäre eine String, beispielsweise die Fehlermeldung »Division durch
Null«, meist werden aber Instanzen von Klassen benutzt. Die Exception wird
mittels des Schlüsselwortes throw ausgelöst.
● Danach wird in den umgebenden Blockbereichen nach einem Handler für die
Exception gesucht. Handler werden also für spezielle Exceptions, sprich Da-
tentypen, definiert. Handler sind durch das Schlüsselwort catch gekennzeich-
net. Die Suche wird vom innersten Block, in dem die Exception aufgetreten ist,
über die umgebenden Blöcke (sprich Funktionen auf dem Stack) fortgesetzt,
bis ein Handler gefunden ist oder die main()-Funktion erreicht wurde (Stack-
Auflösung).
● Der Bereich, für den der Handler zuständig ist, wird mit dem Schlüsselwort
try eingeleitet und in geschweifte Klammern gefaßt.

Beispiele
1: #include <iostream>
2: #include <string.h>
3: using namespace std;

228
Exception-Behandlung

4: class exception {
5: int fakt1, fakt2;
6: public:
7: exception(int i, int j){fakt1=i; fakt2=j;}
8: void ausgabe() {
9: cout << "fakt1 = " << fakt1 << endl;
10: cout << "fakt2 = " << fakt2 << endl;
11: }
12: };
13: float division(int zaehler, int fakt1, int fakt2) {
14: try {
15: if(fakt1*fakt2 == 0) {
16: throw exception(fakt1,fakt2);
17: }
18: }
19: catch(exception& fehlerinstanz) {
20: [Link]();
21: throw "Fehler aufgetreten\n";
22: }
23: return zaehler/(fakt1*fakt2);
24: }
25: int main() {
26: try {
27: float bruch;
28: bruch = division(12,3,0);
29: cout << bruch << endl;
30: }
31: catch (...) {
32: cout << "Exception aufgetreten!" << endl;
33: }
34: return 0;
35: }
Ausgabe des Programms:
fakt1 = 3;
fakt2 = 0;
Exception aufgetreten!

Erläuterung
Die Klasse exception wird definiert, um eine an den Fehler angepaßte Exception
auslösen zu können. Über ihre Datenelemente werden die fehlerrelevanten Informa-
tionen transferiert, ihre Elementfunktion garantiert eine saubere Fehlerbehandlung.
In Zeile 16 wird die Exception vom Typ der Klasse exception ausgelöst und eine
entsprechende Instanz gebildet. Der normale Programmablauf wird daraufhin
unterbrochen. Block für Block wird verlassen und nach einem Handler gesucht, der
bereits in Zeile 19 gefunden wird.

229
Sprachkonzepte und Syntax

Die erste Fehlermeldung wird ausgegeben, und eine zweite Exception, diesmal vom
Typ char*, wird ausgelöst. Wieder wird der Programmablauf unterbrochen, die
return-Anweisung wird nicht ausgeführt.
In Zeile 31 werden alle Exceptions aufgefangen – soweit nicht schon behandelt.
Die zweite Fehlermeldung wird ausgegeben.

Verweise
Siehe Kategorie Funktionen, Funktionen und der Stack

Exceptions auslösen
throw

Beschreibung
Als Anweisung eingesetzt, dient das Schlüsselwort throw dazu, Exceptions auszulösen.
Bei der Funktionsdeklaration kann das Schlüsselwort verwendet werden, um anzugeben, wel-
che Art von Exceptions die deklarierte Funktion auslösen kann.

Anwendung

Exceptions auslösen throw exception


Zum Auslösen einer Exception ruft man das Schlüsselwort throw auf und übergibt
diesem das Exception-Objekt. Dies löst die Exception aus und legt fest, daß das
Argument der Exception-Behandlungsroutine vom gleichen Typ wie das spezifi-
zierte throw-Objekt oder zumindest von einem konvertierbaren Typ sein muß. Auf
diese Weise können Sie unterschiedlichen Fehlern (beispielsweise Zeigerfehler,
Dateifehler etc.) unterschiedliche throw-Objekte und damit unterschiedliche
Behandlungsroutinen zuweisen.
Nach dem Auslösen einer Exception wird der nächstgelegene Handler gesucht, d. h.
derjenige Handler mit passendem Argument, in dessen try-Block zuletzt eingetreten
wurde.
throw-Objekte leben nur so lange, bis die Exception-Behandlung abgeschlossen
wurde (d. h. der catch-Block verlassen wird).
Das Schlüsselwort throw ohne Objekt kann benutzt werden, um Exceptions inner-
halb eines catch-Blocks oder einer Funktion, die in einem catch-Block aufgerufen
wird, erneut auszulösen und so an den nächsten Handler weiterzureichen.

230
Exceptions auslösen

Funktionsdeklaration func() throw;


Das Schlüsselwort throw kann auch am Ende von Funktionsdeklarationen dazu
benutzt werden, die Liste der auszulösenden Exceptions festzulegen:
void func() throw(exception, char*);

Warnung
● Wird in einer Funktion eine Exception ausgelöst, deren Typ nicht in der throw-
Liste aufgeführt ist (vermutlich durch eine in der Funktion aufgerufene Funk-
tion), wird die Funktion unexpected()aufgerufen.
● Eine Funktion, die ohne throw deklariert wurde, kann jede Exception auslösen.
● Eine Funktion, die mit throw() deklariert wurde, kann keine Exception auslö-
sen.
● Eine Funktion, die eine Exception der Klasse A auslösen kann, kann auch Ex-
ceptions einer von A abgeleiteten Klasse auslösen.

Beispiele
class my_exception // Definition einer Exception-Klasse
{
int fakt1, fakt2;
public:
my_exception(int i, int j){fakt1=i; fakt2=j;}
void ausgabe() {
cout << "fakt1 = " << fakt1 << endl;
cout << "fakt2 = " << fakt2 << endl;
}
};

float division(int zaehler, int fakt1, int fakt2)


{
if(fakt1*fakt2 == 0) { // Division durch Null!
throw my_exception(fakt1,fakt2); // Löst Exception vom Typ
} // my_exception aus
return zaehler/(fakt1*fakt2);
}

Verweise
Siehe Exceptions abfangen
Siehe Handler-Bereich festlegen

231
Sprachkonzepte und Syntax

Exceptions abfangen
catch

Beschreibung
Das Schlüsselwort catch zeigt den Beginn einer Behandlungsroutine für Exceptions eines
bestimmten Typs an. Hinter catch steht in Klammern der Exception-Typ, der abgefangen wird.

Anwendung
Mit Hilfe des Schlüsselwortes catch können Exceptions, die in einem vorangehen-
den try-Block ausgelöst wurden, abgefangen werden. Der Typ der ausgelösten
Exception muß mit dem Typ des catch-Handlers übereinstimmen (gewisse Stan-
dardkonvertierungen werden berücksichtigt).
Hinter catch steht in Klammern der Exception-Typ, der abgefangen wird. Der Typ
der ausgelösten Exception muß mit dem Typ des Handlers übereinstimmen. Die
Anweisung catch (...) fängt alle Exceptions auf.
Wird in dem try-Block eine Exception ausgelöst, die von ihrem Datentyp zu einem
catch-Handler paßt, wird der Anweisungsblock des catch-Handlers ausgeführt.

Warnung
● Auf einen try-Block können mehrere Handlerdefinitionen, jeweils mit catch
eingeleitet, folgen. Die Handler werden der Reihe nach überprüft, bis eine
Übereinstimmung gefunden wird.
● Die Anweisung catch (...) fängt alle Exceptions auf. Der Handler catch (...)
sollte daher nur am Ende einer Handler-Liste stehen.

Beispiele
try {
... // Code, in dem Exceptions auftreten können
}
catch (...) { // alle Exceptions abfangen
cout << "Exception aufgetreten!" << endl;
}

Verweise
Siehe Exceptions auslösen
Siehe Handler-Bereich festlegen

232
Handler-Bereich festlegen

Handler-Bereich festlegen
try

Beschreibung
Gültigkeitsbereiche von Handlern fallen nicht mit den üblichen Blöcken zusammen, sondern
werden durch das Schlüsselwort try eingeleitet und in geschweifte Klammern gefaßt. An den
try-Block schließt sich direkt das Schlüsselwort catch mit der Liste der Handler an.

Anwendung
Viele C++-Bibliotheken sind so implementiert, daß die Funktionen und Methoden
der Bibliothek im Falle gravierender Fehler Exceptions auslösen. Wenn Sie diese
(oder selbst definierte und ausgelöste) Exceptions abfangen wollen, müssen Sie die
Anweisungen, die zur Auslösung der Exceptions führen können, in einen try-Block
fassen und an den try-Block einen oder mehrere catch-Handler anfügen.

Beispiele
try {
... // Code, in dem Exceptions auftreten können
}

catch (char* s) { // Exceptions vom Typ char* abfangen


cout << s << endl;
}
catch (...) { // alle Exceptions abfangen
cout << "Exception aufgetreten!" << endl;
}

Verweise
Siehe Exceptions auslösen
Siehe Exceptions abfangen

Verwandte Funktionen
Beschreibung
Mit der Exception-Behandlung sind die Funktionen unexpected() und terminate() sowie
set_unexpected() und set_terminate() verbunden.

233
Sprachkonzepte und Syntax

Anwendung
● Die Funktionen unexpected() und terminate() werden benötigt, um im Falle ei-
nes Versagens der Exception-Behandlung das Programm abzubrechen. Dies ist
zum Beispiel der Fall, wenn innerhalb einer Funktion eine Exception ausgelöst
wird, die die Funktion nicht behandeln soll (throw-Deklaration). In diesem Fall
wird die Funktion unexpected() aufgerufen, die wiederum standardmäßig ter-
minate() aufruft.
● Die Funktion terminate() wird direkt aufgerufen, wenn Stack-Probleme auf-
tauchen oder für eine ausgelöste Exception kein Handler gefunden wurde. Die
Funktion terminate() ruft standardmäßig die Funktion abort() zum Beenden
des Programmes auf.
● Die Funktionen set_unexpected() und set_terminate() dienen dazu, die Funktions-
aufrufe aus unexpected() und terminate() auf eigene Funktionen umzulenken.

Beispiele
#include <iostream>
#include <string>
using namespace std;

// Handlerfunktion für unexpected Exceptions


void unerwartete_Ausnahme() {
cout << "Damit war nicht zu rechnen!" << endl;
terminate();
}

// Funktion, die Exception auslöst


void ausnahme() {
throw string("Fehler aufgetreten!!");

234
C-Strings

// Funktion die keine Exceptions auslösen soll,


// ruft sonst unexpected() auf.
void func() throw() {
ausnahme();
}

int main() {
set_unexpected(unerwartete_Ausnahme); // unexpected-Handler
// registrieren
func(); // unexpected-Exception
// provozieren

return 0;
}

Verweise
Siehe Exceptions auslösen

Zeichenketten

C-Strings
Beschreibung
C kennt keinen eigenen Datentyp für Zeichenketten (Strings). Statt dessen werden Strings ein-
fach als Folgen von Zeichen interpretiert. Ein solcher String beginnt an einer bestimmten Adresse
im Speicher und endet mit dem Auftreten des sogenannten Nullterminierungszeichen '\0'.

Anwendung
Definiert werden Zeichenketten als Zeiger oder Arrays für einen der Datentypen
char (für 7- oder 8-Bit-Zeichensätze wie ASCII oder ANSI) oder wchar_t (für 16-Bit-
Zeichensätze wie UNICODE).
char *ptr;
char str1[25];

235
Sprachkonzepte und Syntax

Die Deklaration als Array hat den Vorteil, daß man gleich mit der Deklaration der
Stringvariablen auch Speicher reserviert. Diesen muß man bei der Definition eines
Zeigers auf eine Zeichenkette nachträglich selbst reservieren (mit malloc() oder new)
– mit dem Vorzug, daß die Größe des Speicherbereichs zur Laufzeit ermittelt und
bei Bedarf auch neuer Speicher reserviert werden kann.
Zur Manipulation der Zeichenketten sind in der C-Laufzeitbibliothek eine Reihe
von Funktionen definiert, die alle mit str... beginnen und in der Header-Datei
string.h deklariert sind.

Warnung
Wenn Sie einen C-String in Form eines Arrays definieren, beachten Sie, daß der
String nicht mit dem Array, sondern mit dem Nullterminierungszeichen '\0' endet.
Wenn Sie also eine Zeichenkette in ein Array kopieren wollen, achten Sie darauf,
daß das Array groß genug ist, um alle Zeichen der Zeichenkette einschließlich des
Nullterminierungszeichens '\0' aufzunehmen. Wenn Sie mit strlen() die Länge
einer Zeichenkette ermitteln wollen, die in einem Array abgelegt ist, erhalten Sie
die Anzahl der Zeichen im String (ohne Nullterminierungszeichen) und nicht die
Größe des Arrays zurück. Wenn Sie mit printf() eine Zeichenkette, die in einem
Array abgelegt ist, ausgeben, werden alle Zeichen von der Adresse des Arrays bis
zum nächsten Nullterminierungszeichen '\0' ausgegeben.
Den String-Funktionen der C-Laufzeitbibliothek haftet das Manko an, daß die
Speicherverwaltung gänzlich dem Programmierer überlassen wird. Will man also
beispielsweise mit Hilfe von strcpy() einen String B in einen String A kopieren,
muß zuvor sichergestellt werden, daß der Speicherplatz, der für String A reserviert
wurde, groß genug ist, um auch String B aufnehmen zu können. Zur Reservierung
von Speicher für Strings gibt es mehrere Möglichkeiten.

Beispiele
#include <stdio.h>
#include <string.h>

int main()
{
char string1[] = "C und C++";
char string2[] = "C++ und C";

if(strcmp(string1, string2) > 0)


printf("%s ist groesser als %s\n",string1,string2);
else
printf("%s ist kleiner oder gleich %s\n", string1,string2);

return 0;
}

236
Die Klasse string

Verweise
Siehe Die Klasse string

Die Klasse string


string

Beschreibung
In C++ kann man zur Programmierung mit Text auf die Klasse string (wstring für Wide Charac-
ter-Strings) zurückgreifen.

Anwendung
Die Klasse string geht zurück auf das Template basic_string, das in der Header-
Datei <string> definiert ist:
template<class charT, ... > class basic_string;
Was wir der Einfachheit halber als string-Klasse bezeichnen, ist also in Wirklich-
keit nichts anderes als ein Alias für die Instanziierung des Templates für den Zei-
chentyp char.
typedef basic_string<char> string;
Analog gibt es eine entsprechende Typdefinition wstring für den Zeichentyp
wchar_t.
Zur Manipulation der Strings verwenden Sie die in basic_string definierten Metho-
den und Operatoren. Die Verwendung dieser Methoden und Operatoren erleichtert
nicht nur die Arbeit mit String (im Vergleich zu den C-Strings), sie ist auch wesent-
lich sicherer, da die Implementierung der string-Klasse für die korrekte Speicher-
verwaltung sorgt.
Zur Unterstützung bestehenden C-Codes verfügt die Klasse string über eine
Methode c_str(), die den in einem string-Objekt gekapselten Text als C-String
zurückliefert.

Beispiele
#include <iostream>
#include <string>
using namespace std;

int main()
{
string str1("C und C++");
string str2 = "C++ und C";

237
Sprachkonzepte und Syntax

if(str1 > str2)


cout << str1 << " ist groesser als " << str2 << endl;
else
cout << str1 << " ist kleiner oder gleich " << str2 << endl;

return 0;
}

Verweise
Siehe Die Klasse string

Wide characters und Multibyte-Zeichen


wchar_t

Beschreibung
Der Datentyp wchar_t (in C noch mittels typedef definiert) für »wide characters« wurde einge-
richtet, um mit Zeichensätzen arbeiten zu können, die entgegen dem ASCII-Zeichensatz nicht
durch 8 Bit codiert werden könne (beispielsweise UNICODE).
Die Wide characters sind von den Multibyte-Zeichen zu unterscheiden. Während
die Wide characters zu den Integer-Typen gehören, werden Multibyte-Zeichen als
Folge von Bytes behandelt. Die Anzahl der Bytes, die zu einem Multibyte-Zeichen
gehören, kann dabei variieren. Dies kann sehr speichersparend sein, beispielsweise
wenn man in einer Datei deutschen Text (für dessen Zeichen man nur 1 Byte benö-
tigt) mit chinesischen Schriftzeichen (für deren Codierung mindestens 2 Byte benö-
tigt werden) mischt. Alle gängigen Multibyte-Codierungsverfahren verwenden
daher irgendwelche Escape-Sequenzen, die dazu dienen, zwischen verschiedenen
Zeichensätzen hin- und herzuschalten und anzuzeigen, ob die nachfolgenden Zei-
chen durch eines oder zwei oder mehrere Bytes codiert werden. Innerhalb eines
Programmes werden Multibyte-Zeichen allerdings wegen ihrer variablen Länge und
unbequemen Handhabung kaum verwendet. Meist wandelt man daher Multibyte-
Zeichen beim Einlesen der Datei in WideCharacter-Zeichen um, arbeitet mit diesen
und schreibt das Ergebnis dann wieder als Multibyte-Zeichen in die Datei zurück.

Anwendung
Die C-Bibliothek enthält etliche Methoden zur Programmierung mit Multibyte-Zei-
chen und Wide characters. Die Multibyte-Funktionen erkennt man an der Zeichen-
folge »mb«, wie in mblen(), mbrlen(), mbtowc(), wctomb() oder mbstowcs(),
wcstombs(), mbsinit(). Die Wide character-Funktionen erkennt man an dem »w« im
Funktionsnamen, wie in wprintf(), wmemcpy() oder wcscpy().

238
Formatierte und unformatierte E/A

Ein- und Ausgabe

Formatierte und unformatierte E/A


Beschreibung
Letztendlich werden Daten (Integer-Werte, Strings, Strukturvariablen, etc.) immer in Form von
Bitströmen ausgetauscht. Dies bedeutet aber nicht, daß man sich auch bei der Programmierung
mit Bitströmen herumschlagen müßte. C und C++ unterstützen den Datenaustausch sowohl in
Form von
● unformatierten Byte-Strömen als auch in
● formatierten Dateneinheiten.

Anwendung
Bei der formatierten Ein- und Ausgabe können die Daten in ihrem ursprünglichen
Datenformat ein- und ausgegeben werden:
int integer = 3;
char zeichen = 'A';
printf("%d",integer); // formatierte Ausgabe in C
printf("%c",zeichen);
cout << integer; // formatierte Ausgabe in C++
cout << zeichen;
Bei der unformatierten Ein- und Ausgabe werden die Daten dagegen als eine Folge
von Bytes behandelt:
fwrite(&zeichen, sizeof(char), 1, stdout); // C
fwrite(&integer, sizeof(int), 1, stdout);
[Link](zeichen); // C++
[Link]((char *) &integer, sizeof(int));
Bei der formatierten Ein- und Ausgabe können die Daten durch explizite Typum-
wandlung im Zuge der Ausgabe auch umformatiert werden. Zudem kann die Aus-
gabe mit Hilfe von Sonderzeichen (\n für Zeilenumbruch, \t für Tabulator) und spe-
ziellen Formatierungsanweisungen weiter formatiert werden.

Warnung
Ein- und Ausgabe sind betriebssystemspezifische Vorgänge. Aus diesem Grund sind
sie auch nicht fest (in Form von Schlüsselworten) in der Sprache verankert, sondern
durch Funktionen/Klassen der Laufzeitbibliothek implementiert. Diese unterstützen
aber nur die Ein- und Ausgabe für Konsolenprogramme. Für Windows-Programme
(unter UNIX XWindows oder OSF Motif) kann man diese Funktionen nicht nut-
zen, sondern muß auf spezielle Funktionen zurückgreifen, die in den APIs der Win-
dows-Systeme enthalten sind.

239
Sprachkonzepte und Syntax

Beispiele
Umformatierung bei der formatierten Ausgabe:
char zeichen = 'A';
printf("%d",zeichen); // Ausgabe: 65
cout << (int) zeichen; // Ausgabe: 65
Verwendung von Sonderzeichen und speziellen Formatierungsanweisungen:
// Feldbreite der Ausgabe auf 5 Zeichen setzen
printf("%5d",integer);
printf("%5c\n",zeichen); // Ausgabe: 3 A

// Feldbreite der Ausgabe auf 5 Zeichen setzen


[Link](5);
cout << integer;
[Link](5);
cout << zeichen << endl; // Ausgabe: 3 A

Verweise
Siehe Referenz der Laufzeitbibliotheken, Beispiele zu Header-Dateien

Streams in C
Beschreibung
Streams sind Datenströme, über die Daten von einer Quelle zu einem Ziel bewegt werden.
Die Stream-Objekte, mit denen wir arbeiten, bezeichnen jeweils ein Ende eines
Datenstroms (Quelle oder Ziel), verfügen über interne Informationen über die
Abwicklung des Datenaustauschs und sind standardmäßig mit einem Zwischenpuf-
fer verbunden.

Anwendung
In C stehen die folgenden Standard-Stream-Objekte zur Verfügung:

stdin Die Standardeingabe, typischerweise die Tastatur


stdout Die Standardausgabe, typischerweise der Bildschirm (genauer gesagt, die Konsole).
stderr Die Standard-Fehlerausgabe, typischerweise die Konsole, allerdings mit der Beson-
derheit, daß dieser Stream nicht gepuffert ist.

Zur Definition eigener Streams, insbesondere zur Ein- und Ausgabe in Dateien,
steht der in <stdio.h> definierte Datentyp FILE zur Verfügung.

240
Streams in C

// mögliche Definition für FILE:


typedef struct {
int level; // Fuellung des Puffers
unsigned flags; // Dateistatus
char fd; // Dateideskriptor
unsigned char hold; // Ungetc char, wenn kein Puffer
int bsize; // Puffergroesse
unsigned char *buffer; // Puffer
unsigned char *curp; // Aktiver Zeiger
unsigned istemp; // Temporaere Datei
short token; // Gueltigkeit
} FILE;
Zur Manipulation der Streams und der Ein- und Ausgabe über die Streams werden
die entsprechenden Funktionen der C-Laufzeitbibliothek verwendet:

C-Funktion Beschreibung
fclose Datenstrom schließen.
feof Testet Datenstrom auf Dateiende.
ferror Testet Datenstrom auf Fehler.
fflush Leert Puffer eines Datenstroms.
fgetc Liest Zeichen von einem Datenstrom.
fgetpos Ermittelt Positionszeiger eines Datenstroms.
fgets Liest eine Zeile von einem Datenstrom.
fopen Öffnet einen Datenstrom.
fprintf Formatierte Ausgabe an einen Datenstrom.
fputc Schreibt ein Zeichen an Datenstrom.
fputs Schreibt einen String an Datenstrom.
freopen Öffnet einen Datenstrom erneut.
fscanf Liest formatiert von Datenstrom.
fseek Positioniert Dateizeiger neu.
fsetpos Positioniert Dateizeiger neu.
ftell Liest Position des Dateizeigers.
getc Liest Zeichen aus Datenstrom.
getchar Liest Zeichen aus Datenstrom stdin.
gets Liest String von stdin.
printf Formatierte Ausgabe an stdout.
putc Schreibt Zeichen in Datenstrom.
putchar Schreibt Zeichen an Datenstrom stdout.
puts Schreibt Zeichenkette an Datenstrom stdout.
rewind Positioniert Dateizeiger auf Anfang des Datenstroms.
scanf Formatierte Eingabe von stdin.

241
Sprachkonzepte und Syntax

C-Funktion Beschreibung
setbuf Einrichtung eines eigenen Datenstrompuffers
setvbuf Datenstrompufferung und Puffergröße verändern.
sprintf Formatierte Ausgabe in einen String.
sscanf Formatierte Eingabe aus einem String.
ungetc Zeichen wieder zurück an Datenstrom schicken.

Streams in C++
Beschreibung
Streams sind Datenströme, über die Daten von einer Quelle zu einem Ziel bewegt werden.
Die Stream-Objekte, mit denen wir arbeiten, bezeichnen jeweils ein Ende eines Datenstroms
(Quelle oder Ziel), verfügen über interne Informationen über die Abwicklung des Datenaus-
tauschs und sind standardmäßig mit einem Zwischenpuffer verbunden.

Anwendung
In C++ stehen die folgenden Standard-Stream-Objekte zur Verfügung:

char wchar_t Externes Gerät


cin wcin Die Standardeingabe, typischerweise die Tastatur
cout wcout Die Standardausgabe, typischerweise der Bildschirm (genauer gesagt,
die Konsole).
cerr wcerr Die Standard-Fehlerausgabe, typischerweise die Konsole, allerdings
mit der Besonderheit, daß dieser Stream nicht gepuffert ist.
clog wclog Die Standard-Protokollausgabe, typischerweise die Konsole.

Eigene Streams können als Instanzen der vordefinierten Stream-Klassen eingerichtet


werden. Zudem besteht die Möglichkeit, von den in der Laufzeitbibliothek defi-
nierten Stream-Templates durch Spezialisierung eigene Stream-Klassen (beispiels-
weise für selbstdefinierte Zeichentypen) abzuleiten.
Zur Manipulation der Streams und der Ein- und Ausgabe über die Streams werden
die Methoden und überladenen Operatoren der Stream-Klassen verwendet.

Formatierung
Formatieren läßt sich die Ausgabe
mittels der folgenden Stream-Methoden

242
Streams in C++

Methode Beschreibung
width() Mit Hilfe der Methode width() kann man für die Ausgabe des nächsten
Werts eine minimale Breite festlegen.
Umfaßt die Ausgabe weniger Stellen, als width() als Argument übergeben
wurde, werden Füllzeichen eingefügt. Das endgültige Format hängt dann
vom ausgewählten Füllzeichen (siehe fill()) und der Ausrichtung (left,
right, internal) ab.
fill() Mit der Methode fill() können Sie ein Füllzeichen festlegen. Füllzeichen
werden verwendet, wenn Sie für eine Ausgabe eine Feldbreite wählen (siehe
oben), die größer ist als die eigentliche Ausgabe.
precision() Mit der Methode precision() kann die Anzahl der Ziffernstellen bei der
Ausgabe von Fließkommazahlen festgelegt werden. Standardwert sind dabei
6 Stellen.
Allerdings ist dabei zu unterscheiden, ob die Fließkommazahlen im Stan-
dardmodus ausgegeben werden, oder ob zuvor eines der Format-Flags fixed
oder scientific gesetzt wurde.
Im Standardmodus legt precision() die Gesamtzahl der Ziffern fest.
Im fixed- oder scientific-Modus legt precision() die Zahl der Nach-
kommastellen fest.

● mittels Formatierungsflags, die über die Methoden setf() und unsetf() gesetzt
und gelöscht werden können. Die Formatierungsflags sind als Elemente der
Klasse ios_base (in nicht ganz aktuellen Compilern ios) definiert:

Flag Wirkung entspricht in C Vorgabe


boolalpha Boolesche Werte als 0
Zahlen oder als Worte
left linksbündige Ausgabe -0 right
right rechtsbündige Ausgabe
internal Freiraum nach Vor-
zeichen oder Basis
dec Dezimaldarstellung %d, %u dec
oct Oktaldarstellung %o
hex Hexadezimaldar- %x
stellung
fixed Feste Stellenzahl %g, %f fixed
scientific Exponentialschreib- %e, %E
weise
showbase Basis anzeigen 0
showpoint Dezimalpunkt anzeigen # 0
showpos Plus-Zeichen mit aus- + 0
geben

243
Sprachkonzepte und Syntax

Flag Wirkung entspricht in C Vorgabe


skipws Whitespace-Zeichen 1
bei Eingabe überlesen
unitbuf Nach Formatierung 0
Ausgabe-Stream leeren
uppercase Bestimmte Klein- %X %E %G 0
buchstaben (z.B. Hex-
Zeichen) als Groß-
buchstaben ausgeben

● mittels Manipulatoren. Dies sind Funktionen, die als Operand an Streamope-


ratoren übergeben werden können.

Manipulator E/A Wirkung


boolalpha e/a wie setf(ios_base::boolalpha)
noboolalpha e/a wie unsetf(ios_base::boolalpha)
left a wie setf(ios_base::left, ios_base::adjustfield)
right a wie setf(ios_base::right, ios_base::adjustfield)
internal a wie setf(ios_base::internal, ios_base::adjustfield)
dec e/a wie setf(ios_base::dec, ios_base::basefield)
oct e/a wie setf(ios_base::oct, ios_base::basefield)
hex e/a wie setf(ios_base::hex, ios_base::basefield)
fixed a wie setf(ios_base::fixed, ios_base::floatfield)
scientific wie setf(ios_base::scientific, ios_base::floatfield)
showbase a wie setf(ios_base::showbase)
noshowbase a wie unsetf (ios_base::showbase)
showpoint a wie setf(ios_base::showpoint)
noshowpoint a wie unsetf (ios_base::showpoint)
showpos a wie setf(ios_base::showpos)
noshowpos a wie unsetf (ios_base::showpos)
skipws e wie setf(ios_base::skipws)
noskipws e wie unsetf(ios_base::skipws)
unitbuf a wie setf(ios_base::unitbuf)
nounitbuf a wie unsetf(ios_base::unitbuf)
uppercase a wie setf(ios_base::uppercase)
nouppercase wie unsetf (ios_base::uppercase)
resetiosflags e/a Flags löschen
(ios_base::fmtflags
mask)
endl a Neue Zeile und Stream leeren

244
Streams in C++

Manipulator E/A Wirkung


ends a Nullterrminierungszeichen ('\t') ausgeben
flush a Stream leeren
setbase(int base) e/a Basis für Integer-Werte
setfill(charT c) e/a wie fill(c)
setiosflags e/a Flags setzen
(ios_base::fmtflags
mask)
setprecision(int n) e/a wie precision(n)
setw(int n) e/a wie width(n)
ws e Whitespace-Zeichen überlesen

Fehlerbehandlung
Zur Fehlerbehandlung enthält jeder Stream die folgenden Statusbits, die im Falle
eines Fehlers von den Streams aus 1 gesetzt werden.

Statusbit Fehler
ios_base::goodbit Kein Fehler aufgetreten, alles ist in Ordnung. (In Wirklichkeit kein
Bit, sondern der Wert 0).
ios_base::eofbit Beim Einlesen wurde das EOF-Zeichen erreicht (kann bei der Eingabe
von Tastatur zur Not durch Strg+D oder Strg+Z simuliert werden).
ios_base::failbit Bei der Eingabe konnte das erwartete Zeichen (beispielsweise wegen
falschem Format) nicht eingelesen werden.
Bei der Ausgabe konnte das gewünschte Zeichen nicht ausgegeben
werden.
ios_base::badbit Der Stream kann aus irgendeinem Grund nicht mehr korrekt arbeiten
(meist ist dies der Fall, wenn es Probleme mit dem zugrundeliegenden
Puffer (basic_streambuf-Objekte) gibt).

Zu den Statusbits gibt es die folgenden Methoden, mit denen der Zustand der Stre-
ams abgefragt werden kann.

Methode Beschreibung
bool good() true, wenn kein Statusbit gesetzt wurde
bool eof() true, wenn eofbit gesetzt wurde
bool fail() true, wenn failbit oder badbit gesetzt wurde
bool bad() true, wenn badbit gesetzt wurde
bool operator!() true, wenn failbit oder badbit gesetzt wurde
iostate rdstate() Liefert den gesamten Streamstatus zurück

245
Sprachkonzepte und Syntax

Pufferung
Beschreibung
Streams sind grundsätzlich gepuffert, d. h., die Eingaben oder Ausgaben erfolgen nicht direkt
zum Ziel des Streams, sondern werden im Speicher zwischengepuffert.
Der Sinn der Pufferung ist es, die Ein- und Ausgabe effizienter zu gestalten. Meist
greift man bei der Ein- oder Ausgabe auf externe Geräte zu (Tastatur, Bildschirm,
Festplatte, Laufwerk). Diese Zugriffe sind stets um ein Vielfaches langsamer als
Zugriffe auf Speicherbereiche. Man kann den Datenaustausch aber beschleunigen,
indem man die Daten Zeichen für Zeichen in einem Puffer im RAM zwischenspei-
chert und dann in möglichst großen zusammenhängenden Blöcken überträgt.

Anwendung
Jeder Puffer hat eine festgelegte Größe. Ist der Puffer voll, leert er sich selbst.
Darüber hinaus gibt es aber auch Möglichkeiten, einen Puffer direkt leeren zu las-
sen.
● Durch Aufruf der Methode flush().
● Der Tastaturpuffer (Streams stdin, cin) kann durch Drücken der Eingabe-
Taste geleert werden.
● Der Konsolenpuffer (Streams stdout, cout, clog) wird bei Ausgabe des New-
line-Zeichens geleert (cout << "\n"; oder cout << endl;). Zudem ist der Ausga-
bepuffer cout (stdout) mit dem Eingabepuffer cin (stdin) verbunden, so daß
vor jeder erwarteten Eingabe der Ausgabepuffer geleert wird.
● Die Fehlerausgabe cerr (stderr) ist nicht gepuffert.
Hinter den Puffern stehen in C++ Klassen, die alle auf das Klassentemplate
basic_streambuf zurückgehen. Die Verbindung zwischen einem Stream und seinem
Puffer wird bei der Instanzbildung des Streams durch den Konstruktor hergestellt.
Nach der Initialisierung kann der Stream über die Methode rdbuf() auf seinen Puf-
fer zugreifen,
● entweder um sich eine Referenz auf den eigenen Puffer zurückliefern zu lassen
und dann diesen über seine public-Schnittstelle zu manipulieren (beispielsweise
zur Anpassung der Puffergröße mit setbuf() )
● oder um den Stream mit einem anderen Puffer zu verbinden (beispielsweise
mit dem Puffer eines anderen Streams).

246
assert.h

Die C-Standardbibliothek

Die Header-Dateien
Um die C-Funktionen in Ihren Programmen aufrufen zu können, müssen Sie zuvor
die Funktionsdeklarationen dem Compiler bekannt machen. Dazu dienen die Hea-
der-Dateien, in denen die Funktionen thematisch geordnet sind, und die Sie mittels
der #include-Direktive in Ihre Programme aufnehmen können.
Im folgenden werden die Funktionen nach Header-Dateien geordnet vorgestellt,
wobei die Namen der C-Konvention verwendet wurden. Nach dem neuen C++-
Standard wird den Dateinamen der C-Header-Dateien jeweils ein »c« vorangestellt
und die Extension weggelassen (stdlib.h wird also zu cstdlib). Der Unterschied zu
den C-Headern ist dabei, daß die Elemente in den C++-Headern im Namensbereich
std deklariert sind.

assert.h
Beschreibung
Enthält allein das Makro assert, das zum Debuggen verwendet werden kann.

Enthaltene Elemente
assert // Prüft eine Bedingung und bricht bei Nichterfüllung
// das Programm ab.

Beispiel
#include <stdio.h>
#include <assert.h>
int main(int argc, char **argv)
{
int i = 3, j = 2;
double erg;
// ... weitere Anweisungen
assert(j != 0); // Division durch Null vermeiden
erg = (double) i/j;
printf("Division ergibt : %f\n",erg);
return 0;
}

247
Die C-Standardbibliothek

ctype.h
Beschreibung
Enthält die Funktionen zur Klassifizierung (is...) und Konvertierung (to...) einfacher Zeichen.
Die Funktionen dieser Header-Datei verwendet man üblicherweise zur Aufbereitung oder Kon-
trolle von Benutzereingaben über die Tastatur. So können Sie testen, ob der Anwender – wie
vom Programm gewünscht – eine Zahl als Ziffernfolge oder unerlaubter Weise als ausgeschrie-
benes Wort eingegeben hat. Oder Sie können Benutzereingaben mit Hilfe der Funktionen tolo-
wer()/toupper() in Klein- oder Großbuchstaben verwandeln.

Enthaltene Elemente
isalnum // Testet, ob Zeichen eine Ziffer oder ein Buchstabe ist.
isalpha // Testet, ob Zeichen ein Buchstabe ist.
iscntrl // Testet, ob Zeichen ein Kontrollzeichen ist.
isdigit // Testet, ob Zeichen eine Zahl ist.
isgraph // Testet, ob Zeichen darstellbar ist.
islower // Testet, ob Zeichen ein Kleinbuchstabe ist.
isprint // Testet, ob Zeichen druckbar ist.
ispunct // Testet, ob Zeichen ein Interpunktionszeichen ist.
isspace // Testet, ob Zeichen ein Zwischenraumzeichen ist.
isupper // Testet, ob Zeichen ein Großbuchstabe ist.
isxdigit // Testet, ob Zeichen eine Hexadezimalziffer ist.
tolower // Wandelt Groß- in Kleinbuchstaben um.
toupper // Wandelt Klein- in Großbuchstaben um.

Beispiel
char zeichen, *str;
...
for(i = 0; i < strlen(str); i++)
str[i] = tolower(str[i]);

if(isprint(zeichen))
putchar(zeichen);

errno.h
Beschreibung
Enthält verschiedene Makros, die von verschiedenen Bibliotheksfunktionen zur Benachrichti-
gung über aufgetretene Fehler verwendet werden.

248
float.h

Enthaltene Elemente
EDOM // Wird im Falle eines ungültigen Funktionsarguments von den
// mathematischen Funktionen in errno kopiert.
EILSEQ // Wird im Falle eines Codierungsfehlers von Multibyte in
// Wide Character oder umgekehrt von den Funktionen
// mbrtowc() bzw. wcrtomb() in errno kopiert.
ERANGE // Wird im Falle eines ungültigen Ergebniswertes von den
// mathematischen Funktionen in errno kopiert.
errno // Wird im Fehlerfall von den mathematischen Funktionen
// gesetzt.

Beispiel
#include <stdio.h>
#include <math.h>
#include <errno.h>
int main(int argc, char **argv)
{
int i = -3;
double wurzel;
errno = 0;
wurzel = sqrt(i);
if(errno == EDOM)
puts("Domain Error bei Aufruf von sqrt()\n");
else
printf("Wurzel von %d ist %f\n",i,wurzel);
return 0;
}

float.h
Beschreibung
Enthält verschiedene Makros, die zu verschiedenen implementierungsspezifischen Konstanten
expandieren. Aufgeführt sind nur die Konstanten für den Datentyp float. Die Konstanten für
double und long double beginnen mit den Suffixen DBL beziehungsweise LDBL. (FLT_ROUNDS
gilt für alle drei Gleitkommatypen).

Enthaltene Elemente
FLT_DIG // Anzahl der signifikanten Ziffern in der Mantisse,
// wenn dargestellt zur Basis 10
FLT_EPSILON // Differenz zwischen 1 und der nächstgrößeren
// darstellbaren Zahl.
FLT_MANT_DIG // Anzahl der Ziffern in der Mantisse, wenn dargestellt
// zur Basis FLT_RADIX
FLT_MAX // Größte positive Zahl.
FLT_MAX_10_EXP // Größte positive Zahl für den Exponenten zur Basis 10.

249
Die C-Standardbibliothek

FLT_MAX_EXP // Größte positive Zahl für den Exponenten zur


// Basis FLT_RADIX
FLT_MIN // Kleinste positive Zahl (Wie nah kommt man an 0 heran)
FLT_MIN_10_EXP // Kleinste negative Zahl für den Exponenten zur
// Basis 10.
FLT_MIN_EXP // Kleinste negative Zahl für den Exponenten zur
// Basis FLT_RADIX
FLT_RADIX // Basis des Exponenten
FLT_ROUNDS // Modus, nach dem Zahlen gerundet werden:
// -1 unbestimmt
// 0 zu Null
// 1 zum nächsten Wert
// 2 zu +unendlich
// 3 zu -unendlich

ios646.h
Beschreibung
Synonyme für bestimmte Operatoren.

Enthaltene Elemente
Synonym für
and && Logische UND-Verknüpfung
and_eq &= Bitweise UND-Verknüpfung und Zuweisung
bitand & Bitweise UND-Verknüpfung
bitor | Bitweises ODER
compl ~ Komplement
not ! Nicht-Operator, Verneinung
not_eq != vergleicht zwei arithmetische Operanden auf Ungleichheit
or || Logisches ODER
or_eq |= Bitweises ODER und Zuweisung des Ergebnisses
xor ^ Bitweises exklusives ODER
xor_eq ^= Bitweises exklusives ODER und Zuweisung des Ergebnisses

250
limits.h

limits.h
Beschreibung
Enthält Konstanten, die Größe und Wertebereiche der elementaren Datentypen festlegen (die
Werte sind implementierungsspezifisch und werden vom Compiler festgelegt).

Enthaltene Elemente
CHAR_BIT // Anzahl der Bits in kleinstem Datentyp
CHAR_MIN // kleinster Wert für Objekte vom Typ char
CHAR_MAX // größter Wert für Objekte vom Typ char
INT_MIN // kleinster Wert für Objekte vom Typ int
INT_MAX // größter Wert für Objekte vom Typ int
LONG_MIN // kleinster Wert für Objekte vom Typ long int
LONG_MAX // größter Wert für Objekte vom Typ long int
MB_LEN_MAX // maximale Anzahl von Bytes in Multibyte-Zeichen
SCHAR_MIN // kleinster Wert für Objekte vom Typ signed char
SCHAR_MAX // größter Wert für Objekte vom Typ signed char
SHRT_MIN // kleinster Wert für Objekte vom Typ short int
SHRT_MAX // größter Wert für Objekte vom Typ short int
UCHAR_MAX // größter Wert für Objekte vom Typ unsigned char
UINT_MAX // größter Wert für Objekte vom Typ unsigned int
ULONG_MAX // größter Wert für Objekte vom Typ unsigned long int
USHRT_MAX // größter Wert für Objekte vom Typ unsigned short int

locale.h
Beschreibung
Enthält die Funktionen localeconv() und setlocale() zum Einstellen und Abfragen landes-
spezifischer Eigenheiten. Rückgabetyp von localeconv() ist die Struktur lconv. Die LC-Makros
können setlocale() als Argument übergeben werden, um spezielle Facetten einer Lokale aus-
zuwählen.

Enthaltenen Elemente
LC_ALL // Alle Kategorien landesspez. Einstellungen.
LC_COLLATE // Für String-Vergleiche.
LC_CTYPE // Für die Zeichenklassifizierung und -umwandlung.
LC_MONETARY // Für Währungsformate.
LC_NUMERIC // Für Zahlenformate, beispielsweise Dezimalpunkt in
// Gleitkommazahlen.
LC_TIME // Für Datums- und Zeitangaben.
struct lconv // Die Struktur lconv .
localeconv // Die Struktur lconv initialisieren.
setlocale // Landesspezifische Werte abfragen und verändern.

251
Die C-Standardbibliothek

Beispiel
Aktuelle Lokale-Einstellungen abfragen:
struct lconv ll;
struct lconv *conv = &ll;
conv = localeconv();
printf("Dezimalpunkt : %s\n", conv->decimal_point);
Lokale wechseln
setlocale(LC_ALL, "de_DE");

math.h
Beschreibung
Deklariert die mathematischen Funktionen. Während unter C nur die double-Versionen der
Funktionen verfügbar sind, sind unter C++ zusätzlich für die Datentypen float und long
double überladen.

Enthaltene Elemente
HUGE_VAL // Makro, das zu einem double-Wert expandiert, der von den
// math. Funktionen im Falle eines Überlaufes
// zurückgeliefert wird.
acos // Arkuskosinus berechnen.
asin // Arkussinus berechnen.
atan // Arkustangens von x berechnen.
atan2 // Arkustangens von x/y berechnen.
ceil // Rundet auf nächste Ganzzahl auf.
cos // Kosinus berechnen.
cosh // Kosinus hyperbolicus berechnen.
exp // Exponentialfunktion berechnen.
fabs // Ermittelt Absolutwert.
floor // Größte Ganzzahl ermitteln, die kleiner oder gleich dem
// Argument ist.
fmod // Rest einer Gleitkomma-Division berechnen.
frexp // Exponentialwert berechnen.
ldexp // Gleitkommazahl multiplizieren.
log // Natürlichen Logarithmus berechnen.
log10 // Logarithmus zur Basis 10 berechnen.
modf // Argument in ganzzahligen und gebrochenen Teil zergliedern
pow // Zahl potenzieren.
sin // Sinus berechnen.
sinh // Sinus hyperbolicus berechnen.
sqrt // Quadratwurzel berechnen.
tan // Tangens berechnen.
tanh // Tangens hyperbolicus berechnen.

252
setjmp.h

Beispiel
double zahl;
printf("Geben Sie ein Zahl: \n\n");
scanf("%lf", &zahl); fflush(stdin);
printf(" Quadrat von %lf = %lf\n",zahl,zahl*zahl);
printf(" %lf^3 = %lf\n",zahl,pow(zahl,3));
printf(" Log.e von %lf = %lf\n",zahl,log(zahl));
printf(" Log.10 von %lf = %lf\n",zahl,log10(zahl));
printf(" Sinus von %lf (RAD) = %lf\n",zahl,sin(zahl));
printf(" Sinus von %lf (GRAD) = %lf\n",zahl,sin(2*3.1415*zahl/360));

setjmp.h
Beschreibung
Definiert den Datentyp jmp_buf, der von dem Makro setjmp() und der Funktion longjmp()
benutzt wird.

Enthaltene Elemente
jmp_buf // Nimmt die Werte der aktuellen Umgebung, typischerweise
// die Inhalte der Prozessorregister sowie Stack- und
// Framezeiger auf, um einen nicht lokalen Sprung zu
// ermöglichen.
longjmp // Aufrufumgebung gemäßt jmp_buf-Argument wiederherstellen
// nach nicht lokalem Sprung.
setjmp // Aufrufumgebung in jmp_buf-Argument sichern. Umgebung
// kann mittels longjmp() wiederhergestellt werden.

Beispiel
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>

void func(jmp_buf sprung)


{
puts("Sprung aus Funktion heraus durchfuehren\n");
longjmp(sprung,1);
}

int main(int argc, char** argv)


{
int wert;
jmp_buf sprung;
if(wert = setjmp(sprung))
{
printf("Aus Sprung mit Wert %d zurueckgekehrt\n", wert);
exit(wert);
}

253
Die C-Standardbibliothek

func(sprung);
return 0;
}

signal.h
Beschreibung
Definiert Konstanten und Funktionen, die für die Signalbearbeitung (Interrupts, Segmentation
faults, etc.) erforderlich sind. Die SIG_-Konstanten sind kompatibel zum zweiten Parameter von
signal(), dem ansonsten eine Signalbehandlungsfunktion übergeben wird. Die SIG-Konstan-
ten kategorisieren die Signale und dienen als Argumente für den ersten Parameter der
signal()-Funktion.

Enthaltenen Elemente
SIG_DFL // Standardverarbeitung
SIG_ERR // Rückgabewert von signal(), wenn Fehler auftritt
SIG_IGN // Signal ignorieren
SIGABRT // Unnormales Programmende
SIGFPE // Gleitkommafehler
SIGILL // Unzulässige Anweisung
SIGINT // Strg+C-Interrupt
SIGSEGV // Unzulässiger Speicherzugriff (Segmentation Fault)
SIGTERM // An Programm gesendete Beendigungsanfrage
raise // Sendet ein Signal.
signal // Installiert Signalbehandlungsfunktion für die
// Verarbeitung eines SIG-Signals.

Beispiel
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void Signalbearbeitung(int par) {
/* Signalbehandlung reinstallieren */
signal(SIGFPE, Signalbearbeitung);
printf("Signal abgefangen!\n");
printf("Programmdaten werden zur Analyse abgespeichert\n");
exit(1);
}
int main(int argc, char** argv) {
/* Signalbehandlung reinstallieren */
signal(SIGFPE, Signalbearbeitung);
int n, i = 3265;
printf("Geben Sie eine ganze Zahl ein: \n");
scanf("%d",&n);
fflush(stdin);

254
stdarg.h

i = i/n;
printf("%d\n", i);
return 0;
}

stdarg.h
Beschreibung
Definiert die Makros, mit denen Funktionen mit einer variablen Anzahl von Argumenten verar-
beitet werden können.

Enthaltene Elemente
va_list // Array-Typ für va_arg, va_end und va_start.
va_arg // Ermittelt Zeiger auf nächstes Argument in der Liste.
va_end // Setzt Zeiger nach Bearbeitung der Argumente zurück.
va_start // Makro, das der Funktion einen korrekten Rücksprung
// ermöglicht..

stddef.h
Beschreibung
Definiert einige wichtige Typen und Makros, die vor allem bibliotheksintern verwendet werden.

Enthaltene Elemente
NULL // Wert des Null-Zeigers
offsetof // Ermittelt den Offset eines Elements in einer Struktur.
ptrdiff_t // ganzzahliger, vorzeichenbehafteter Datentyp, der das
// Ergebnis der Subtraktion zweier Zeiger
// repräsentieren kann
size_t // vorzeichenloser Ganzzahltyp, der von sizeof als
// Ergebnistyp verwendet wird.
wchar_t // Zeichentyp für umfangreichere Zeichensätze (16 bis
// 32-Bit)

stdio.h
Beschreibung
Enthält die Funktionen zur Ein- und Ausgabe (Konsole, Tastatur, Dateien), sowie etliche ver-
wandte Konstanten und Datentypen.

255
Die C-Standardbibliothek

Enthaltene Makros und Typdefinitionen


_IOFBF // für setbuf(); zeigt an, daß ein Stream gepuffert wird (0)
_IOLBF // für setbuf(); Stream zeilenweise gepuffert (1)
_IONBF // für setbuf(); Stream nicht gepuffert (2)
BUFSIZ // Das Makro BUFSIZ wird von fopen(),freopen() und setbuf()
// benutzt, um bei Einrichtung eines Streams automatisch
// die Größe des Streampuffers festzulegen. (>= 255)
EOF // Negative Ganzzahlkonstante, zeigt das Ende einer Datei an
FILE // Ein Datentyp, der alle Informationen aufnehmen kann, die
// zur Durchführung von Datei-Operationen erforderlich sind.
// Der Aufbau des Datentyps ist implementierungsspezifisch.
FILENAME_MAX // Die maximale Anzahl der Zeichen, die in einem
// Dateinamen vorkommen dürfen.
FOPEN_MAX // FOPEN_MAX enthält die maximale Anzahl der Datenströme,
// die gleichzeitig von einem Programm geöffnet werden
// können. Dieser Wert beträgt mindestens 8, wobei jedes
// Programm automatisch die Standard-Datenströme stdin,
// stdout und stderr erhält. Programme, die mehr als fünf
// weitere Datenströme benötigen, können anhand des
// Makros überprüfen, ob sie ihnen vom System zur
// Verfügung gestellt werden können.
fpos_t // Der Type fpos_t wird von fgetpos() und fsetpos() benutzt,
// um die aktuelle Position in einer Datei zu spezifizieren
L_tmpnam // Größe eines Arrays vom Datentyp char, das groß genug sein
// muß, um mit tmpnam() generierte Dateinamen aufzunehmen

// Die folgenden drei Makros, die als Argument für die


// Funktion fseek() verwendet werden, legen fest von
// welcher Position aus der Dateizeiger bewegt werden soll:

SEEK_CUR // Ab aktueller Position (1).


SEEK_END // Ab Dateiende (2).
SEEK_SET // Ab Dateianfang (0).
size_t // vorzeichenloser Ganzzahltyp, der von sizeof als
// Ergebnistyp verwendet wird.
stderr // Standard-Fehlerstream.
stdin // Standard-Eingabestream.
stdout // Standard-Ausgabestream.
TMP_MAX // TMP_MAX entspricht der maximalen Anzahl von
// eindeutigen temporären Dateinamen, die mit der
// Funktion tmpnam() erzeugt werden können. Der Wert von
// TMP_MAX darf nicht kleiner sein als 25.

Enthaltene Funktionen
clearerr // Fehlerbedingung aus Stream entfernen.
fclose // Stream schließen.
feof // Testet Stream auf Dateiende.
ferror // Testet Stream auf Fehler.
fflush // Leert Puffer eines Streams.

256
stdlib.h

fgetc // Liest Zeichen von einem Stream.


fgetpos // Ermittelt Positionszeiger eines Streams.
fgets // Liest eine Zeile von einem Stream.
fopen // Öffnet einen Stream.
fprintf // Formatierte Ausgabe an einen Stream.
fputc // Schreibt ein Zeichen in einen Stream.
fputs // Schreibt einen String in einen Stream.
fread // Liest Daten von einem Stream.
freopen // Öffnet einen Stream erneut.
fscanf // Liest formatiert von Stream.
fseek // Positioniert Dateizeiger neu.
fsetpos // Positioniert Dateizeiger neu.
ftell // Liest Position des Dateizeigers.
fwrite // Schreibt Daten unformatiert an Stream.
getc // Liest Zeichen aus Stream.
getchar // Liest Zeichen aus Stream stdin.
gets // Liest String von stdin.
perror // Schreibt Fehlermeldung an stdout.
printf // Formatierte Ausgabe an stdout.
putc // Schreibt Zeichen in Stream.
putchar // Schreibt Zeichen an Stream stdout.
puts // Schreibt Zeichenkette an Strean stdout.
remove // Löscht eine Datei.
rename // Benennt eine Datei um.
rewind // Positioniert Dateizeiger auf Anfang des Streams.
scanf // Formatierte Eingabe von stdin.
setbuf // Streampufferung verändern.
setvbuf // Streampufferung und Puffergröße verändern.
sprintf // Formatierte Ausgabe an einen String.
sscanf // Formatierte Eingabe von einem String.
tmpfile // Temporäre Datei erzeugen.
tmpnam // Temporären Dateinamen erzeugen.
ungetc // Zeichen wieder zurück an Stream schicken.
vfprintf // Formatierte Ausgabe an Stream.
vprintf // Formatierte Ausgabe an stdout.
vsprintf // Formatierte Ausgabe in String.

stdlib.h
Beschreibung
Sammelsurium häufig benötigter Bibliotheksfunktionen, zu denen u. a. die dynamische Spei-
cherverwaltung und die Prozeßkontrollroutinen gehören.

257
Die C-Standardbibliothek

Enthaltene Makros und Typdefinitionen


div_t // div_t ist eine Struktur, die von der Funktion div()
// zurückgegeben wird. Das Strukturelement quot erhält
// den Quotienten, rem den Rest der Division.
EXIT_FAILURE // Statuscode, der zusammen mit der Bibliotheksfunktion
// exit() benutzt werden kann, um anzuzeigen, daß das
// Programm mit einem Fehler beendet wurde.
EXIT_SUCCESS // Statuscode, der zusammen mit der Bibliotheksfunktion
// exit() benutzt werden kann, um anzuzeigen, daß das
// Programm erfolgreich beendet wurde.
ldiv_t // wie div_t für die Funktion ldiv().
MB_CUR_MAX // Dieses Makro enthält die maximale Anzahl von Bytes
// pro Zeichen im aktuellen Zeichensatz.
NULL // Wert des NULL-Zeigers.
RAND_MAX // Enthält die größte Pseudo-Zufallszahl, die von der
// Funktion rand() zurückgegeben werden kann.
size_t // vorzeichenloser Ganzzahltyp, der von sizeof als
// Ergebnistyp verwendet wird.
wchar_t // Zeichentyp für umfangreichere Zeichensätze (16 bis
// 32-Bit)

Enthaltene Funktionen
abort // Beendet Programm unverzüglich.
abs // Ermittelt Absolutwert einer Integerzahl (In C++ für
// long int, float und long double überladen).
atexit // Funktion registrieren, die beim Programmende
// ausgeführt werden soll.
atof // Wandelt String in Fließkommazahl um.
atoi // Wandelt String in Integerzahl um.
atol // Wandelt String in long int um.
bsearch // Binäre Suche durchführen.
calloc // Speicher allokieren und initialisieren.
div // Ganzzahldivision durchführen (In C++ für long überladen).
exit // Programm beenden.
free // Dynamisch angeforderten Speicher freigeben.
getenv // Eintrag in Programm-Umgebung lesen.
labs // Absolutwert einer Zahl vom Typ long int ermitteln.
ldiv // Ganzzahldivision mit Zahlen vom Typ long int (In C++ für
// long überladen).
malloc // Speicher anfordern.
mblen // Länge eines Multibyte-Zeichens ermitteln.
mbstowcs // Zeichenkette mit Zeichen, die aus mehreren Bytes
// bestehen, in Wide Character-String umwandeln.
mbtowc // Zeichen, das aus mehreren Bytes besteht, in
// Wide Character umwandeln
qsort // QuickSort durchführen.
rand // Pseudo-Zufallszahl erzeugen.
realloc // Speicherblock neu zuordnen.
srand // Pseudo-Zufallszahl erzeugen.

258
string.h

strtod // String in Gleitkommazahl (Typ double) umwandeln.


strtol // String in long int umwandeln.
strtoul // String in unsigned long umwandeln.
system // Programm unterbrechen und anderes Programm ausführen.
wcstombs // Zeichenkette mit Wide Characters in Multibyte-String
// umwandeln.
wctomb // Wide Character in Multibyte-Zeichen umwandeln.

string.h
Beschreibung
Enthält die Funktionen zur Manipulation von Zeichenketten (Strings).

Enthaltenen Elemente
NULL // Wert des NULL-Zeigers.
size_t // vorzeichenloser Ganzzahltyp, der von sizeof als
// Ergebnistyp verwendet wird.
memchr // Sucht in einem Speicherbereich nach erstem Vorkommen
// eines Zeichens.
memcmp // Vergleicht zwei Speicherbereiche.
memcpy // Kopiert Anzahl Zeichen von einem Speicherbereich in einen
// anderen.
memmove // Kopiert Zeichen von einem Speicherbereich in einen
// anderen, der sich mit dem Ursprungsbereich überlappen darf
memset // Initialisiert einen Speicherbereich mit einem Zeichen.
strcat // Fügt Zeichenkette an eine andere an.
strchr // Ermittelt Zeiger auf erstes Vorkommen eines Zeichens in
// String.
strcmp // Vergleicht zwei Zeichenketten.
strcoll // Vergleicht zwei Zeichenketten.
strcpy // Kopiert einen String in einen anderen.
strcspn // Sucht in Zeichenkette nach Zeichen, die in anderer
// Zeichenkette nicht enthalten sind.
strerror // Übersetzt eine Fehlernummer in eine Zeichenkette.
strlen // Ermittelt die Länge einer Zeichenkette.
strncat // Fügt n Zeichen einer Zeichenkette an andere an.
strncmp // Vergleicht einen String mit einem Teil eines anderen
// Strings.
strncpy // Kopiert n Zeichen eines Strings in einen anderen.
strpbrk // Sucht nach erstem Vorkommen eines beliebigen Zeichens aus
// einer Zeichenkette in einer anderen Zeichenkette.
strrchr // Ermittelt Zeiger auf letztes Vorkommen eines Zeichens in
// einer Zeichenkette.
strspn // Ermittelt Index des ersten Zeichens in einer Zeichenkette,
// das nicht zum Zeichensatz einer zweiten
// Zeichenkette gehört

259
Die C-Standardbibliothek

strstr // Ermittelt erstes Vorkommen einer Zeichenkette in einer


// anderen.
strtok // Sucht nach nächstem Grundsymbol in Zeichenkette.
strxfrm // Wandelt String unter Berücksichtigung landesspezifischer
// Gegebenheiten um.

Beispiel
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv)
{
char str[3][21] = {"String1", "String2", "String3"};
char *p_str;
int bytes;

// Strings aneinanderhaengen
// Speicherbereich ermitteln
bytes = (strlen(str[0]) + strlen(str[1]) +
strlen(str[2]) + 1)*sizeof(char);
// Speicher allokieren
p_str = (char*) malloc(bytes);
strcpy(p_str,str[0]);
strcat(p_str,str[1]);
strcat(p_str,str[2]);
printf("String = %s enthaelt %d Bytes\n",p_str,bytes);
free(p_str);
return 0;
}

time.h
Beschreibung
Enthält die Datentypen time_t und clock_t sowie die Datenstruktur tm und die allgemeinen
Zeitfunktionen.

Anwendung
Für Zeitnahmen geht man üblicherweise so vor, daß man sich die Startzeit und die
Endzeit von der Funktion time() als Werte des Datentyps time_t zurückliefern läßt.
Die Differenz läßt man sich von der Funktion difftime() errechnen.
Um Zeit und/oder Datum abzufragen, kann man beispielsweise die Funktion asc-
time() verwenden. Für die Umwandlung des Datums in einen ausgabefähigen String
nutzt man die Funktion strftime().

260
time.h

Enthaltene Makros und Typdefinitionen


clock_t // clock_t ist der Datentyp, der von der Funktion
// clock() zurückgegeben wird.
CLOCKS_PER_SEC // CLOCKS_PER_SEC enthält die Anzahl der Ticks pro
// Sekunden. Ein Tick ist die Maßeinheit, mit der von
// der Funktion clock() die Zeit gemessen wird.
NULL // Wert des NULL-Zeigers.
size_t // vorzeichenloser Ganzzahltyp, der von sizeof als
// Ergebnistyp verwendet wird.
time_t // Der Typ time_t ist ein arithmetischer Typ zur
// Aufnahme von Zeitangaben.
tm // Die Struktur tm enthält alle Elemente, um Zeit- und
// Datumsinformationen aufzunehmen. Das Muster wird von
// den Funktionen localtime() und gmtime() verwendet.

Enthaltene Funktionen
asctime // Wandelt eine als Struktur gespeicherte Zeit in eine
// Zeichenkette um.
clock // Ermittelt, wieviel Ticks seit dem Start des aufrufenden
// Prozesses verbraucht wurden.
ctime // Wandelt Zahl vom Typ time_t in Zeichenkette um.
difftime // Ermittelt die Differenz zwischen zwei Zeiten.
gmtime // Berechnet aus lokaler Zeit und definierter Zeitdifferenz
// die Greenwich Mean Time (GMT).
localtime // Wandelt einen Zeitwert vom Typ time_t in die Lokalzeit um
mktime // Wandelt Zeit aus Struktur in Kalenderzeit um.
strftime // Formatiert Zeit nach landesspezifischen Bedingungen.
time // Gibt aktuelle Zeit an Variable vom Typ time_t zurück.

Beispiel
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char** argv)
{
time_t start, ende;
char eingabe[100];
int ergebnis;
start = time(NULL);
puts("Wieviel ist 7 * 23: \n");
fgets(eingabe,100,stdin);
sscanf(eingabe,"%d\n",&ergebnis);
ende = time(NULL);
printf("Sie haben %d sec. benoetigt\n",(int) difftime(ende,start));
if(ergebnis == 161)
puts("Die Loesung ist korrekt \n");
else
printf("Die korrekte Antwort ist 161 (nicht %d)\n", ergebnis);
return 0;
}

261
Die C-Standardbibliothek

wchar.h
Beschreibung
Enthält die Funktionen zur Bearbeitung von Wide Character und Multibyte-Strings (inklusive
Ein- und Ausgabe).

Enthaltene Makros und Typdefinitionen


mbstate_t // Typdefinition, in der Informationen für die Konvertierung
// von Multibyte-Zeichen in Wide Character-Zeichen und
// vice versa abgelegt werden.
NULL // Wert des NULL-Zeigers.
size_t // vorzeichenloser Ganzzahltyp; Ergebnistyp von sizeof
tm // Struktur zum Ablegen von Zeit- und Datumsinformationen
// aufzunehmen, siehe Funktionen localtime() und gmtime().
wchar_t // Zeichentyp für umfangreichere Zeichensätze (16 / 32-Bit)
WCHAR_MAX // WCHAR_MAX enthält den größten Wert des Typs wchar_t
WCHAR_MIN // WCHAR_MIN enthält den kleinsten Wert des Typs wchar_t
WEOF // Konstante, die das Ende einer Datei anzeigt
wint_t // Integer-Typ für die Codierung von Zeichen aus erweiterten
// Zeichensätzen.

Enthaltene Funktionen
btowc // Wandelt ein 1-MultiByte-Zeichen in ein
// Wide Character-Zeichen um.
fgetwc // Liest Zeichen von einem Stream.
fgetws // Liest eine Zeile von einem Stream.
fputwc // Schreibt ein Zeichen in Stream.
fputws // Schreibt einen String in Stream.
fwide // Kann einen Stream nachträglich für Byte- oder
// Wide Character-Zeichen einrichten.
fwprintf // Formatierte Ausgabe an stdout.
fwscanf // Liest formatiert von Stream.
getwc // Liest Zeichen aus Stream.
getwchar // Liest Zeichen aus Stream stdin.
mbrlen // Länge eines Multibyte-Zeichens ermitteln.
mbrtowc // Multibyte-Zeichen in Wide Character umwandeln.
mbsinit // Ermittelt, ob sein Argument einen anfänglichen
// Konvertierungsmodus anzeigt.
mbsrtowcs // Multibyte-Zeichenkette in Wide Character-String umwandeln
putwc // Schreibt Zeichen in Stream.
putwchar // Schreibt Zeichen an Stream stdout.
swprintf // Formatierte Ausgabe in einen String.
swscanf // Formatierte Eingabe von einem String.
ungetwc // Zeichen wieder zurück an Stream schicken.
vfwprintf // Formatierte Ausgabe an Stream.
vswprintf // Formatierte Ausgabe in String.
vwprintf // Formatierte Ausgabe an stdout.
wcrtomb // Wide Character in Multibyte-Zeichen umwandeln.

262
wctype.h

wcscat // Fügt Zeichenkette an eine andere an.


wcschr // Ermittelt Zeiger auf erstes Vorkommen eines Zeichens in
// einem String
wcscmp // Vergleicht zwei Zeichenketten.
wcscoll // Vergleicht zwei Zeichenketten.
wcscpy // Kopiert einen String in einen anderen.
wcscspn // Sucht in Zeichenkette nach Zeichen, die in anderer
// Zeichenkette nicht enthalten sind.
wcsftime // Formatiert Zeit nach landesspezifischen Bedingungen.
wcslen // Ermittelt die Länge einer Zeichenkette.
wcsncat // Fügt n Zeichen einer Zeichenkette an andere an.
wcsncmp // Vergleicht einen String mit einem Teil eines
// anderen Strings
wcsncpy // Kopiert n Zeichen eines Strings in einen anderen.
wcspbrk // Sucht nach erstem Vorkommen eines beliebigen Zeichens aus
// einer Zeichenkette in einer anderen Zeichenkette.
wcsrchr // Ermittelt Zeiger auf letztes Vorkommen eines Zeichens in
// einer Zeichenkette.
wcsrtombs // Wide Character-String in Multibyte-String umwandeln
wcsspn // Liefert Index des ersten Zeichens in einer Zeichenkette,
// das nicht zum Zeichensatz einer anderen
// Zeichenkette gehört
wcsstr // Ermittelt erstes Vorkommen einer Zeichenkette in einer
// zweiten Zeichenkette.
wcstod // String in Gleitkommazahl (Typ double) umwandeln.
wcstok // Sucht nach nächstem Grundsymbol in Zeichenkette.
wcstol // String in long int umwandeln.
wcstoul // String in unsigned long int umwandeln.
wcsxfrm // Wandelt String unter Berücksichtigung landesspezifischer
// Gegebenheiten um.
wctob // Wandelt Zeichen in ein 1-MultiByte-Zeichen um
wmemchr // Sucht in einem Speicherbereich nach erstem Vorkommen
// eines Zeichens.
wmemcmp // Vergleicht zwei Speicherbereiche.
wmemcpy // Kopiert Anzahl Zeichen von einem Speicherbereich in einen
// anderen.
wmemmove // Kopiert von einem Speicherbereich in einen anderen,
// der sich mit dem Ursprungsbereich überlappen darf
wmemset // Initialisiert einen Speicherbereich mit einem Zeichen.
wprintf // Formatierte Ausgabe an stdout.
wscanf // Formatierte Eingabe von stdin.

wctype.h
Beschreibung
Enthält die Funktionen zur Klassifizierung und Konvertierung von Wide Character-Zeichen,
sowie einige Hilfstypen.

263
Die C-Standardbibliothek

Enthaltene Elemente
wctrans_t // Hilfstyp für Zeichenabbildungen.
wctype_t // Hilfstyp für die Zeichenklassifizierung.
WEOF // Konstante, die das Ende einer Datei anzeigt
wint_t // Integer-Typ für die Codierung von Zeichen aus
// erweiterten Zeichensätzen
iswalnum // Testet, ob Zeichen eine Ziffer oder ein Buchstabe ist.
iswalpha // Testet, ob Zeichen ein Buchstabe ist.
iswcntrl // Testet, ob Zeichen ein Kontrollzeichen ist.
iswctype // Testet, ob Zeichen einer bestimmten Klasse angehört.
// Die Klasse wird durch einen Aufruf von wctype()
// spezifiziert.
iswdigit // Testet, ob Zeichen eine Zahl ist.
iswgraph // Testet, ob Zeichen druckbar ist (Leerzeichen
// ausgenommen).
iswlower // Testet, ob Zeichen ein Kleinbuchstabe ist.
iswprint // Testet, ob Zeichen druckbar ist.
iswpunct // Testet, ob Zeichen ein Interpunktionszeichen ist.
iswspace // Testet, ob Zeichen ein Zwischenraumzeichen ist.
iswupper // Testet, ob Zeichen ein Großbuchstabe ist.
iswxdigit // Testet, ob Zeichen eine Hexadezimalziffer ist.
towctrans // Konvertiert ein Wide Character Zeichen.
towlower // Wandelt Groß- in Kleinbuchstaben um.
towupper // Wandelt Klein- in Großbuchstaben um.
wctrans // Ermittelt eine Abbildung von einem Wide Character-
// Zeichensatz in einen anderen (nach LC_TYPE).
wctype // Wird zusammen mit iswctype() verwendet und erlaubt die
// Identifizierung einer Klasse anhand eines Strings.

Die Funktionen der C-Standardbibliothek


abort <stdlib.h>
Prozeß beenden

Beschreibung
Die Funktion abort() bewirkt einen unnormalen Programmabbruch, was bedeutet, daß im
Gegensatz zur Funktion exit() nicht sichergestellt ist, daß Dateipuffer geleert, offene Streams
geschlossen und mit tmpfile() erzeugte temporäre Dateien entfernt werden. Außerdem wer-
den die Programmbeendigungsroutinen, die mit atexit() eingerichtet worden sind, nicht auf-
gerufen. Dafür wird die Funktion raise() mit der Konstanten SIGABRT als Argument aufgerufen,
für das man eine Signalbehandlungsroutine einrichten kann.

264
wctype.h

Parameter
void abort(void);

Verwandte Funktionen
assert(), atexit(), exit(), raise()

abs <stdlib.h>
Absolutwert berechnen

Beschreibung
Die Funktion abs() gibt den Betrag ihres ganzzahligen Argumentes als Funktionswert zurück.
Der Betrag einer Zahl ist ihr Abstand zur Null.

Parameter
int abs(int n);
● Rückgabewert. Betrag des Arguments n.

Verwandte Funktionen
fabs(), labs()

acos <math.h>
Bogenkosinus berechnen

Beschreibung
Die Funktion acos() berechnet den Bogenkosinus (Umkehrfunktion des Kosinus) für das über-
gebene Argument.

Parameter
double acos(double zahl);
● zahl. Argument, für das der Arkuskosinus berechnet wird (muß im Bereich
zwischen -1.0 und 1.0 liegen)
● Rückgabewert. Arkuskosinus des Arguments im Bereich [0,p].

Verwandte Funktionen
asin(), atan(), cos(), sin(), tan()

asctime <time.h>
Uhrzeit in Zeichenkette

265
Die C-Standardbibliothek

Beschreibung
Die Funktion asctime() wandelt die in der Zeitstruktur tm enthaltenen Zeitinformationen in
eine Zeichenkette um. Die erzeugte Zeichenkette besitzt das folgende Format (für Lokale "C"):
Mon Jul 31 [Link] 1989\n\0

Parameter
char *asctime (const struct tm *zeit);
● Rückgabewert. Zeiger auf die erzeugte Zeichenkette.

Verwandte Funktionen
ctime(), gmtime(), localtime(), setlocale()

asin <math.h>
Bogensinus berechnen

Beschreibung
Die Funktion asin() berechnet den Bogensinus (Umkehrfunktion des Sinus) für das überge-
bene Argument.

Parameter
double asin(double zahl);
● zahl. Argument, für das der Arkussinus berechnet wird (muß im Bereich zwi-
schen -1.0 und 1.0 liegen)
● Rückgabewert. Arkussinus des Arguments im Bereich [-p /2, + p /2].

Verwandte Funktionen
acos(), atan(), cos(), sin(), tan()

assert <assert.h>
Diagnosemeldung ausgeben

Beschreibung
Das Makro assert überprüft den Wert eines übergebenen Ausdrucks. Liefert diese Überprüfung
das Ergebnis falsch (0), gibt assert() eine Diagnosemeldung auf den Standardfehler-Stream
stderr aus und ruft anschließend die Funktion abort() auf, um das Programm abzubrechen.
Die Meldung von assert beinhaltet den Dateinamen und die Zeilennummer, in der das Makro
aufgerufen wurde. Die Informationen werden den Konstanten __FILE__ und __LINE__ entnom-
men. Durch Setzen des Schalters NDEBUG (#define NDEBUG) können nachfolgende assert-Auf-
rufe unterdrückt werden.

266
wctype.h

Parameter
void assert(int ausdruck);
● ausdruck. Der zu überprüfende Ausdruck.

Verwandte Funktionen
abort(), exit(), raise(), signal()

atan, atan2 <math.h>


Bogentangente berechnen

Beschreibung
Die Funktion atan() berechnet die Bogentangente einer Zahl. atan2() berechnet die
Bogentangente von zahl1/zahl2.

Parameter
double atan(double zahl);
double atan2(double zahl1, double zahl2);
● Rückgabewert. atan() liefert Arcustangens von zahl im Bereich [-p /2, + p /2],
atan2()liefert Arcustangens von zahl1/zahl2 im Bereich [-p , + p ].

Verwandte Funktionen
acos(), asin(), cos(), sin(), tan()

atexit <stdlib.h>
Funktion bei exit aufrufen

Beschreibung
Mit der Funktion atexit() können Sie eine Funktion registrieren lassen, die beim Program-
mende aufgerufen werden soll. Hiermit kann die Abarbeitung von notwendigen Aufräumarbei-
ten bei Beendigung eines Programms eingerichtet werden.
Die mit atexit() registrierten Funktionen werden aufgerufen, wenn das Programm mit exit()
beendet oder von main() aus die return-Anweisung erfolgt. Wurden mehrere Funktionen durch
aufeinanderfolgende Aufrufe von atexit() registriert, werden sie in der umgekehrten Reihen-
folge ihrer Registrierung aufgerufen.

Parameter
int atexit(void (*func)(void));
● Rückgabewert. Die Funktion atexit() gibt eine Null zurück, wenn die überge-
bene Funktion registriert werden konnte.

267
Die C-Standardbibliothek

Verwandte Funktionen
abort(), exit()

atof <stdlib.h>
Umwandlung: Zeichenkette in double

Beschreibung
Die Funktion atof() (ascii to float) wandelt die Zeichenkette, auf die string zeigt, in eine Gleit-
kommazahl doppelter Genauigkeit um und gibt diese Zahl als Funktionswert zurück. Führende
Leerzeichen und Tabulatoren werden übersprungen, die Umwandlung wird bei dem ersten Zei-
chen, das nicht mehr als Ziffer erkannt wird, abgebrochen.

Parameter
double atof(const char *string);
● Rückgabewert. Korrespondierender double-Wert.

Verwandte Funktionen
atoi(), atol(), strtod()

atoi <stdlib.h>
Umwandlung: String in int

Beschreibung
Die Funktion atoi() (ascii to int) wandelt den übergebenen String in eine Zahl vom Datentyp
int um. Führende Zwischenraumzeichen werden übersprungen, ein eventuell vorhandenes
Vorzeichen jedoch berücksichtigt. Beim ersten nicht als Ziffer identifizierbaren Zeichen wird
die Umwandlung abgebrochen und die bis dahin ermittelte Zahl zurückgegeben.

Parameter
int atoi(const char *string);
● Rückgabewert. Korrespondierender int-Wert oder Null.

Verwandte Funktionen
atof(), atol(), strtod(), strtol()

atol <stdlib.h>
Umwandlung: String in long

268
wctype.h

Beschreibung
Die Funktion atol() (ascii to long) wandelt den übergebenen String in eine Zahl vom Datentyp
long um. Führende Zwischenraumzeichen werden übersprungen, ein eventuell vorhandenes
Vorzeichen jedoch berücksichtigt. Beim ersten nicht als Ziffer identifizierbaren Zeichen wird
die Umwandlung abgebrochen und die ermittelte Zahl zurückgegeben.

Parameter
long atol(const char *string);
● Rückgabewert. Korrespondierender long int -Wert oder Null.

Verwandte Funktionen
atof(), atoi(), strtod(), strtol()

bsearch <stdlib.h>
Binäre Suche

Beschreibung
Mit der Funktion bsearch() kann eine binäre Suche in einem sortierten Datenfeld durchgeführt
werden. Der bei der Suche notwendige Vergleich wird durch eine Funktion durchgeführt, deren
Adresse an bsearch() übergeben wird. Diese Funktion muß zwei Elemente miteinander ver-
gleichen und folgende Werte an bsearch() zurückgeben:
< 0 Das erste Element ist kleiner als das zweite.
0 Beide Elemente sind identisch.
> 0 Das erste Element ist größer als das zweite.

Parameter
void *bsearch (const void *suchobj, const void *basis,
size_t anzahl, size_t breite,
int (*vgl) (const void *elem1, const void *elem2));
● suchobj. Objekt, für das eine Übereinstimmung gesucht wird (Wird als erstes
Argument an vgl() übergeben).
● basis. Zeiger auf Anfang des Feldes, in dem gesucht werden soll.
● anzahl. Anzahl der Elemente in Feld.
● breite. Größe jedes Elements in Bytes.
● vgl. Zeiger auf Funktion, die zwei Elemente vom Typ const void* vergleicht.
● Rückgabewert. Ist die Suche erfolgreich, gibt die Funktion einen Zeiger auf
das erste Elemente in dem Feld zurück, das dem Suchkriterium genügt. Konnte
kein passendes Element gefunden werden, wird ein NULL-Zeiger zurückgege-
ben.

269
Die C-Standardbibliothek

Warnung
Wenn das Feld noch nicht sortiert ist, kann vorher die Funktion qsort() aufgerufen
werden.

Verwandte Funktionen
qsort()

btowc <wchar.h>
1-Byte-Zeichen umwandeln

Beschreibung
Wandelt ein 1-MultiByte-Zeichen in ein Wide Character-Zeichen um.

Parameter
wint_t btowc(int c);
● Rückgabewert. Wide Character-Repräsentation des übergebenen Zeichens.
WEOF, wenn das Zeichen kein gültiges 1-MultiByte-Zeichen im anfänglichen
Konvertierungsstatus oder EOF war.

Verwandte Funktionen
wctob()

calloc <stdlib.h>
Speicher zuordnen

Beschreibung
Mit calloc() kann Speicherplatz für ein Feld von anzahl Elemente der Größe groesse einge-
richtet und mit Nullen initalisiert werden.

Parameter
void *calloc(size_t anzahl, size_t groesse);
● Rückgabewert. Konnte die Speicheranforderung erfüllt werden, gibt die Funk-
tion einen Zeiger auf den allokierten Speicherbereich, anderenfalls einen
NULL-Zeiger zurück.

Verwandte Funktionen
malloc(), realloc()

270
wctype.h

ceil <math.h>
Rundungsfunktion

Beschreibung
Die Funktion ceil() berechnet den kleinstmöglichen ganzzahligen Wert, der größer oder
gleich ihrem double-Argument ist und gibt ihn zurück.

Parameter
double ceil(double zahl);
● Rückgabewert. Aufgerundeter Wert.

Verwandte Funktionen
floor(), fmod()

clearerr <stdio.h>
Fehleranzeige zurücksetzen

Beschreibung
Die Funktion setzt das Fehler- und Dateiende-Flag für einen Stream zurück.

Parameter
void clearerr(FILE *stream);

Verwandte Funktionen
feof(), ferror()

clock <time.h>
Dauer des aufrufenden Prozesses

Beschreibung
Die Funktion gibt die vom aufrufenden Prozeß verbrauchte Prozessorzeit als Wert vom Typ
clock_t zurück. Der Konstanten CLOCKS_PER_SEC entspricht die Anzahl der Ticks pro Sekunde.
Wenn der von clock() zurückgegebene Wert durch die Konstante CLOCKS_PER_SEC geteilt wird,
erhält man die Prozessorzeit in Sekunden.

Parameter
clock_t clock(void);
● Rückgabewert. Liefert die seit einem implementierungsspezifischen Zeitpunkt
vergangene Prozessorzeit. Kann die Anzahl der Ticks nicht ermittelt werden,
wird der Wert -1 zurückgeliefert.

271
Die C-Standardbibliothek

Verwandte Funktionen
difftime(), time()

cos, cosh <math.h>


Kosinus berechnen

Beschreibung
Die Funktionen cos() und cosh() berechnen den Kosinus bzw. den Kosinus hyperbolicus des
übergebenen Arguments (Winkel in Bogenmaß) und sind für alle reellen Zahlen definiert.

Parameter
double cos(double zahl);
double cosh(double zahl);
● Rückgabewert. cos() liefert den Kosinus des Arguments im Bereich [-1, 1].
cosh() liefert den Kosinus hyperbolicus des Arguments im Bereich [1, 8].

Warnung
Der Kosinus hyperbolicus steigt sehr schnell an.

Verwandte Funktionen
asin(), atan(), atan2(), sin(), sinh()
Siehe Beispiel zu Header-Datei math.h

ctime <time.h>
Zeit in Zeichenkette

Beschreibung
Die Funktion ctime() wandelt die als Variable vom Typ time_t übergebene Kalenderzeit in eine
Zeichenkette um. Die erzeugte Zeichenkette besitzt das lokal verwendete Format, beispiels-
weise:
Fre Jun 30 [Link] 1988\n\0 // für die C-Lokale
Entspricht dem Aufruf asctime(localtime(ptr_zeit));.

Parameter
char * ctime(const time_t *ptr_zeit);
● Rückgabewert. Zeiger auf die erzeugte Zeichenkette.

Verwandte Funktionen
asctime(), gmtime(), localtime()

272
wctype.h

difftime <time.h>
Differenz zwischen zwei Zeiten

Beschreibung
Die Funktion difftime() ermittelt die Differenz zwischen zwei Zeiten vom Typ time_t und gibt
das Ergebnis in Sekunden zurück.

Parameter
double difftime(time_t neuezeit, time_t altezeit);
● Rückgabewert. Differenz zwischen beiden Zeiten.

Verwandte Funktionen
asctime(), ctime(), localtime(), time()
Siehe Beispiel zu Header-Datei time.h

div <stdlib.h>
Quotient und Rest zweier Ganzzahlen

Beschreibung
Die Funktion div() teilt eine Ganzzahl (zahl1) durch eine zweite (zahl2) und gibt das Ergebnis
als eine Variable vom Strukturtyp div_t zurück.

Parameter
div_t div(int zahl1, int zahl2);
● Rückgabewert. Die Funktion gibt eine Variable vom Typ div_t zurück, in der
Quotient (.quot) und Divisionsrest (.rem) festgehalten sind.

Verwandte Funktionen
ldiv()

exit <stdlib.h>
Prozeß beenden

Beschreibung
Die Funktion exit() beendet ein Programm, nachdem die mit atexit() registrierten Funktio-
nen in der umgekehrten Folge ihrer Registrierung abgearbeitet, der Streampuffer geleert,
offene Dateien geschlossen und mit tmpfile() erzeugte temporäre Dateien entfernt wurden.
Das Argument status spezifiziert einen Statuscode (z. B. die ANSI-C-Konstanten EXIT_FAILURE
oder EXIT_SUCCESS), der an das aufrufende Programm übergeben wird. Unter MS-DOS kann in
Batchdateien dieser Wert mit IF ERRORLEVEL abgefragt werden.

273
Die C-Standardbibliothek

Parameter
void exit(int status);

Verwandte Funktionen
abort(), atexit(), system()

exp <math.h>
Exponential berechnen

Beschreibung
Die Funktion exp() berechnet die Exponentialfunktion ihres Arguments. Sie ist das Gegenstück
der Funktion log().

Parameter
double exp(double zahl);
● Rückgabewert. Die Funktion liefert bei Erfolg den Exponentialwert (e^zahl),
HUGE_VAL bei zu großem Ergebniswert.

Verwandte Funktionen
log(), log10(), pow()
Siehe Beispiel zu Header-Datei math.h

fabs <math.h>
Gleitkomma-Absolutwert berechnen

Beschreibung
Die Funktion fabs() berechnet den Betrag einer Gleitkommazahl und gibt ihn zurück.

Parameter
double fabs(double zahl);
● Rückgabewert. Betrag des Arguments.

Verwandte Funktionen
abs(), ceil(), floor(), fmod(), labs()

fclose <stdio.h>
Stream schließen

274
wctype.h

Beschreibung
Die Funktion schließt den Stream, dessen Zeiger ihr als Argument übergeben wurde. Dabei wird
der mit dem Stream verbundene Puffer geleert, im Puffer befindliche ausgegebene Daten in die
Datei geschrieben, im Puffer befindliche gelesene Daten gelöscht.

Parameter
int fclose(FILE *stream);
● Rückgabewert. Bei Erfolg gibt die Funktion eine Null zurück, sonst EOF.

Verwandte Funktionen
fflush(), setbuf(), setvbuf()

feof <stdio.h>
Stream auf Dateiende prüfen

Beschreibung
Die Funktion feof() prüft, ob das Dateiende-Flag des Streams, dessen Zeiger übergeben
wurde, gesetzt ist.

Parameter
int feof(FILE *stream);
● Rückgabewert. Wenn die gegenwärtige Position das Dateiende ist, wird ein
Wert ungleich Null zurückgegeben, sonst Null.

Verwandte Funktionen
ferror(), perror()

ferror <stdio.h>
Stream auf Fehler prüfen

Beschreibung
Die Funktion ferror() prüft, ob ein Schreib- oder Lesefehler für den Datenstrom stream aufge-
treten ist. Entsprechende Fehler-Flags werden nicht zurückgesetzt (dies kann durch Aufruf von
rewind() oder Schließen des Streams geschehen).

Parameter
int ferror(FILE *stream);
● Rückgabewert. Im Fehlerfall ein Wert ungleich Null, sonst Null.

275
Die C-Standardbibliothek

Verwandte Funktionen
feof(), fopen(), perror(), rewind()

fflush <stdio.h>
Stream entleeren

Beschreibung
Diese Funktion leert den Puffer, der mit dem übergebenen Stream verbunden ist. Handelt es
sich um einen Ausgabe-Stream, werden die gepufferten Daten in die zugehörige Datei
geschrieben. Nach ANSI C ist das Verhalten undefiniert, wenn es sich um einen Eingabe-Stream
handelt. Die meisten Compiler leeren dann den Puffer.

Parameter
int fflush(FILE *stream);
● Rückgabewert. Bei Erfolg wird eine Null zurückgegeben, ansonsten EOF.

Verwandte Funktionen
fclose(), setbuf(), setvbuf()

fgetc, fgetwc <stdio.h><wchar.h>


Zeichen aus Stream lesen

Beschreibung
Die Funktion liest ein Zeichen aus dem Datenstrom, auf den stream zeigt, und rückt den Datei-
zeiger vor.

Parameter
int fgetc(FILE *stream);
wint_t fgetwc(FILE *stream);
● Rückgabewert. Die Funktion gibt das gelesene Zeichen als int-Wert ohne Vor-
zeichen zurück; EOF (WEOF) kann einen Fehler oder das Ende der Datei bedeu-
ten.

Verwandte Funktionen
gets(), fputc(), ungetc()

fgetpos <stdio.h>
Stream-Positionsangabe holen

276
wctype.h

Beschreibung
Die Funktion fgetpos() kopiert den Wert des Stream-Positionszeigers in die Variable, auf die
pos zeigt. Der Datentyp von pos ist fpos_t, der in der Header-Datei <stdio.h> definiert ist.

Parameter
int fgetpos(FILE *stream, fpos_t *pos);
● Rückgabewert. Im Fehlerfall ein Wert ungleich Null, sonst Null.

Verwandte Funktionen
fsetpos(), ftell()

fgets, fgetws <stdio.h><wchar.h>


String aus Stream lesen

Beschreibung
Die Funktion liest so lange Zeichen von stream, bis entweder anz-1 Zeichen gelesen wurden,
das Zeichen für Zeilenvorschub (\n) gelesen oder das Dateiende erreicht wurde. Die Funktion
terminiert den eingelesenen String automatisch durch Anhängung des Nullterminierungszei-
chens (\0).

Parameter
char *fgets(char *zkette, int anz, FILE *stream);
wchar_t *fgetws(wchar_t *zkette, int anz, FILE *stream);
● Rückgabewert. Die Funktion gibt, wenn erfolgreich, einen Zeiger auf zkette
zurück, im Fehlerfall oder bei frühzeitigem Dateiende einen NULL-Zeiger.

Verwandte Funktionen
fputs(), gets(), puts()

floor <math.h>
Abrunden

Beschreibung
Die Funktion floor() berechnet den größtmöglichen ganzzahligen Wert, der kleiner/gleich
dem Argument ist, und gibt ihn zurück.

Parameter
double floor(double zahl);
● Rückgabewert. Abgerundeter Wert für zahl.

277
Die C-Standardbibliothek

Verwandte Funktionen
ceil()

fmod <math.h>
Gleitkomma-Rest berechnen

Beschreibung
Die Funktion fmod() teilt x durch y und gibt den Rest der Division zurück.

Parameter
double fmod(double x, double y);
● Rückgabewert. Gleitkommarest der Division.

Verwandte Funktionen
ceil(), fabs(), floor(), modf()

fopen <stdio.h>
Datei öffnen

Beschreibung
Die Funktion fopen() öffnet eine Datei und initialisiert den Stream, der mit der Datei verbun-
den ist. Das Argument modus legt fest, in welchem Modus die Datei geöffnet werden soll.

Modus Beschreibung
r Zum Lesen öffnen.
w Zum Schreiben öffnen (Datei wird überschrieben oder bei Bedarf erzeugt).
a Zum Schreiben an das Dateiende öffnen (Datei wird bei Bedarf erzeugt).
r+ Datei soll zum Lesen und Schreiben geöffnet werden und muß existieren.
w+ Leere Datei soll zum Lesen und Schreiben geöffnet werden (Datei wird
überschrieben oder bei Bedarf erzeugt).
a+ Zum Lesen und Anhängen öffnen (Datei wird bei Bedarf erzeugt).

Parameter
FILE *fopen(const char *datei, const char *modus);
● Rückgabewert. Die Funktion gibt einen Zeiger auf eine Struktur vom Typ FILE
zurück. Dieser Zeiger wird dann an die weiteren Funktionen, die auf dem St-
ream operieren sollen, als Argument übergeben. Konnte die Datei nicht geöff-
net werden, wird ein NULL-Zeiger zurückgegeben.

278
wctype.h

Warnung
Die Modusspezifikation kann durch Anhängen von t oder b jeweils explizit im
Text- oder Binärmodus geöffnet werden (betrifft Codierung des Zeilenumbruchs).
Dateistreams, die zum Lesen und Schreiben geöffnet wurden, müssen fflush() oder
eine Funktion zur Positionierung des Dateizeigers (fseek(), rewind()) ausführen,
bevor zwischen Lesen und Schreiben gewechselt werden kann.

Verwandte Funktionen
fclose(), ferror(), freopen()

fprintf, fwprintf <stdio.h><wchar.h>


Formatierte Ausgabe an Stream

Beschreibung
Die Funktion erzeugt aus ihren Argumenten eine Zeichenkette, die in den Datenstrom, auf den
stream zeigt, geschrieben wird. Die Formatierung der Zeichenkette erfolgt wie für printf()
beschrieben.

Parameter
int fprintf(FILE *stream, const char *format...);
int fwprintf(FILE *stream, const wchar_t *format...);
● stream. Zeiger auf FILE-Struktur des Ausgabe-Streams.
● format. Formatzeichenkette (siehe printf()).
● .... Variable Anzahl von Argumenten.
● Rückgabewert. Die Funktion gibt die Anzahl der ausgegebenen Zeichen zu-
rück. Im Fehlerfall wird ein negativer Wert zurückgeliefert (meist EOF (WEOF)).

Verwandte Funktionen
fscanf(), fputs(), fwrite(), printf()

fputc, fputwc <stdio.h><wchar.h>


Zeichen an Stream ausgeben

Beschreibung
Die Funktion gibt ein einzelnes Zeichen an einen Stream aus.

Parameter
int fputc(int zeichen, FILE *stream);
wint_t fputwc(wchar_t zeichen, FILE *stream);

279
Die C-Standardbibliothek

● Rückgabewert. Die Funktion gibt das geschriebene Zeichen zurück. Ist der
Rückgabewert EOF (WEOF), ist ein Fehler aufgetreten.

Verwandte Funktionen
fgetc(), fgets(), putc(), ungetc()

fputs, fputws <stdio.h><wchar.h>


Zeichenkette an Stream schreiben

Beschreibung
Die Funktion schreibt eine Zeichenkette an einen Stream. Das den String beendende Nulltermi-
nierungszeichen wird nicht mit ausgegeben.

Parameter
int fputs(const char *zkette, FILE *stream);
int fputws(const wchar_t *zkette, FILE *stream);
● Rückgabewert. Die Funktion gibt im Erfolgsfall einen nicht-negativen Wert
zurück. Ist der Rückgabewert EOF (WEOF), ist ein Fehler aufgetreten.

Verwandte Funktionen
fputc(), fprintf(), putc(), putchar(), getc(), gets()

fread <stdio.h>
Daten aus Stream lesen

Beschreibung
Für Binärdateien. Die Funktion fread() liest anzahl Elemente der Größe groesse (in Bytes) aus
einem Stream ein nach puffer. Mit ihr können beispielsweise in der Datei enthaltene Struktu-
ren in ein entsprechendes Feld von Strukturen eingelesen werden.

Parameter
size_t fread (void *puffer, size_t groesse,
size_t anzahl, FILE *stream);
● Rückgabewert. Anzahl der fehlerfrei gelesenen Datenelemente.

Verwandte Funktionen
fopen(), fwrite(), printf(), scanf()

free <stdlib.h>
Speicher freigeben

280
wctype.h

Beschreibung
Die Funktion gibt den Speicherbereich frei, auf den addr verweist und der zuvor mit einer der
Funktionen malloc(), calloc() oder realloc() angefordert wurde.

Parameter
void free(void *addr);

Tip
Der Funktion kann auch ein Zeiger auf Null übergeben werden, in welchem Falle
jedoch kein Code ausgeführt wird.

Verwandte Funktionen
malloc(), calloc(), realloc()
Siehe Praxisteil, Kategorie Zeiger und dynamische Speicherverwaltung, Speicheral-
lokation mit malloc()

freopen <stdio.h>
Dateizeiger neu zuordnen

Beschreibung
Die Funktion schließt die Datei, die mit dem übergebenen Datenstrom stream verbunden ist.
Anschließend wird dem Stream die durch das Argument pfad angegebene Datei mit den ange-
gebenen Zugriffsberechtigungen (siehe fopen()) zugeordnet. Diese Funktion wird üblicher-
weise verwendet, um die Umleitung der Standard-Streams (stdin, stdout, stderr) in Dateien
vorzunehmen.

Parameter
FILE *freopen(const char *pfad, const char *modus, FILE *stream);
● Rückgabewert. Die Funktion gibt bei Erfolg einen Zeiger zur neu geöffneten
Datei zurück, bei Versagen einen NULL-Zeiger.

Verwandte Funktionen
fopen(), fclose()

frexp <math.h>
Gleitkommazahl aufteilen

Beschreibung
Die Funktion frexp() zerlegt eine Gleitkommazahl in eine normalisierte Mantisse und ihren
Exponenten zur Basis 2 auf. Die Mantisse ist größer/gleich 0.5 und kleiner als 1.

281
Die C-Standardbibliothek

Parameter
double frexp(double zahl, int *exp);
● Rückgabewert. Die Funktion gibt die Mantisse zurück. Der Exponent wird in
die Variable geschrieben, auf die *exp zeigt.

Verwandte Funktionen
exp(), ldexp()

fscanf, fwscanf <stdio.h><wchar.h>


Formatiert aus Stream lesen

Beschreibung
Die Funktion liest Daten formatiert aus dem Datenstrom stream ein. Sie benutzt das Argument
format (siehe scanf()), um die eingelesenen Zeichen in die richtigen Datentypen umzuwan-
deln. Die eingelesenen Daten werden dann an die Speicherstellen geschrieben, die mit den
weiteren Funktionsargumenten übergeben werden. Für jedes weitere Funktionsargument muß
in der Formatzeichenkette ein Typbezeichner angegeben worden sein.

Parameter
int fscanf(FILE *stream, const char *format,...);
int fwscanf(FILE *stream, const wchar_t *format,...);
● stream. Zeiger auf FILE-Struktur des Eingabe-Streams.
● format. Formatzeichenkette (siehe printf()).
● .... Variable Anzahl von Argumenten.
● Rückgabewert. Die Funktion gibt die Anzahl der erfolgreich umgewandelten
und zugewiesenen Felder zurück. Ist der Rückgabewert EOF, wurde versucht,
das Dateiende einzulesen.

Verwandte Funktionen
fprintf(), scanf(), sscanf()

fseek <stdio.h>
Dateizeiger positionieren

Beschreibung
Die Position bewegt den Dateizeiger eines Streams zu einer bestimmten Stelle.

282
wctype.h

Parameter
int fseek(FILE *stream, long offset, int urprung);
● offset. Definiert die Entfernung in Bytes, die der Dateizeiger von der Stelle, die
im Argument ursprung kodiert ist, bewegt werden soll. Für binäre Dateien ist
dies die Anzahl der Zeichen, die der Dateizeiger bewegen soll (kann auch ne-
gativ sein), für Textdateien sollte der Wert Null oder von ftell() zurückgelie-
fert worden sein, wobei Ursprung gleich SEEK_SET sein muß.
● ursprung. Eine von drei Konstanten, die als Bzeug für den offset dienen:
SEEK_CUR Ab der aktuellen Position.
SEEK_END Ab dem Ende der Datei.
SEEK_SET Ab dem Anfang der Datei.

● Rückgabewert. Die Funktion gibt eine Null zurück, wenn der Dateizeiger be-
wegt werden konnte, sonst einen Wert ungleich Null.

Verwandte Funktionen
ftell(), rewind()

fsetpos <stdio.h>
Positionsanzeige bestimmen

Beschreibung
Mit der Funktion fsetpos() können Sie die Positionsanzeige des Streams auf einen Wert
zurücksetzen, wie er beispielsweise bei einem Aufruf der Funktion fgetpos() ermittelt wurde.

Parameter
int fsetpos(FILE *stream, const fpos_t *pos);
● pos. Position, auf die der Positionszeiger gesetzt werden soll (abgespeicherter
Rückgabewert der Funktion fgetpos() ).
● Rückgabewert. Die Funktion gibt im Erfolgsfall eine Null zurück, im Fehler-
fall einen Wert ungleich Null.

Verwandte Funktionen
fseek(), fgetpos()

ftell <stdio.h>
Stream-Zeigerposition ermitteln

283
Die C-Standardbibliothek

Beschreibung
Die Funktion ftell() gibt den aktuellen Wert des Positionszeigers zurück, der mit dem Argu-
ment stream verbunden ist.

Parameter
long ftell(FILE *stream);
● Rückgabewert. Die Funktion gibt die aktuelle Position zurück. Der Rückgabe-
wert unterscheidet sich, je nachdem, ob es sich um eine Binär- oder eine Textda-
tei handelt. Für eine Binärdatei gibt die Funktion die Anzahl der Bytes vom
Dateianfang bis zur aktuellen Position zurück. Für eine Textdatei ist der Wert
nur zur Weitergabe an fseek() geeignet. Im Fehlerfall ist der Rückgabewert -1L.

Verwandte Funktionen
fgetpos(), fseek(), rewind()

fwide <wchar.h>
Stream-Orientierung

Beschreibung
Ermittelt und ändert möglicherweise die Orientierung eines Streams. Ist modus = 0 wird die
Orientierung nicht geändert, ist modus > 0 wird versucht, eine Wide Character-Orientierung
herzustellen, ist modus < 0 wird versucht, eine Byte-Orientierung herzustellen

Parameter
int fwide (FILE *stream, int modus);
● Rückgabewert. Ein Wert > 0 zeigt an, daß der Stream Wide Characterorien-
tiert ist, ein Wert < 0 zeigt an, das der Stream byteorientiert ist.

Verwandte Funktionen
fgetwc(), fgetws(), fwscanf(), getwc(), fputwc(), wscanf(), fwprintf(), fputwc(),
fputws(), putwc(), wprintf()

fwrite <stdio.h>
In einen Stream schreiben

Beschreibung
Für Binärdateien. Die Funktion fwrite() schreibt anzahl Datenelemente der Größe groesse (in
Bytes) aus dem Speicherbereich, auf den puffer verweist, in den Datenstrom stream. Nach dem
Schreibvorgang wird der Stream-Positionszeiger auf den neuen Stand gebracht.

284
wctype.h

Parameter
size_t fwrite (const void *puffer, size_t groesse,
size_t anzahl, FILE *stream);
● Rückgabewert. Anzahl der tatsächlich geschriebenen Datenelemente.

Verwandte Funktionen
fread(), write()

getc, getwc, getchar, getwchar <stdio.h><wchar.h>


Ein Zeichen einlesen

Beschreibung
Die Funktionen getc() und getwc() lesen ein Zeichen aus einem Stream ein, getchar() und
getwchar() lesen ein Zeichen aus dem Stream stdin. Das Makro getchar() entspricht dem Auf-
ruf getc(stdin), das Makro getwchar() dem Aufruf getwc(stdin).

Parameter
int getc(FILE *stream);
wint_t getwc(FILE *stream);
int getchar(void);
wint_t getwchar(void);
● Rückgabewert. Die Funktionen geben das eingelesene Zeichen zurück; EOF
(WEOF) wird beim Erreichen des Dateiendes oder bei Auftreten eines Fehlers zu-
rückgeliefert.

Verwandte Funktionen
fgetc(), putc(), putchar(), ungetc()

getenv <stdlib.h>
Wert aus Umgebung holen

Beschreibung
Die Funktion getenv() untersucht die betriebssystemspezifische Umgebung eines Programms.
Sie sucht nach einem Eintrag, der mit dem Argument varname identisch ist, und gibt bei Erfolg
einen Zeiger auf die entsprechende Umgebungsvariable zurück.

Parameter
char *getenv(const char *varname);
● varname. Umgebungsvariable, nach der gesucht wird.
● Rückgabewert. Liefert einen Zeiger auf die Definition der Umgebungsvaria-
blen zurück, oder einen NULL-Zeiger, wenn die Variable nicht definiert ist.

285
Die C-Standardbibliothek

Verwandte Funktionen
setlocale(), localeconv()

gets <stdio.h>
Zeile von stdin lesen

Beschreibung
Die Funktion gets() liest eine Zeichenkette vom Standardeingabe-Stream und speichert sie an
der mit str übergebenen Adresse. Das Einlesen wird beendet, wenn die Funktion das Zeichen
für Zeilenvorschub oder EOF entdeckt. Das Zeichen für Zeilenvorschub wird entfernt und durch
das Nullterminierungszeichen (\0) ersetzt, mit dem das Ende des Strings markiert wird.

Parameter
char *gets(char *str);
● Rückgabewert. Zeiger auf eingelesenen String; im Fehlerfall ein NULL-Zeiger.

Warnung
Beachten Sie, daß der Speicherbereich, auf den str zeigt, groß genug sein muß, um
den String aufzunehmen, da die Funktion ansonsten den Speicher überschreibt.

Verwandte Funktionen
fgets(), fputs(), puts()

gmtime <time.h>
Zeitwert in Struktur umwandeln

Beschreibung
Die Funktion gmtime() erwartet als Argument die Adresse einer Variablen vom Typ time_t. Die
in dieser Variablen gespeicherte Kalenderzeit (meist erhalten durch einen Aufruf der Funktion
time()), wird von der Funktion in Greenwich Mean Time (auch UTC genannt) umgewandelt und
in der Struktur tm abgelegt.

Parameter
struct tm *gmtime(const time_t *zeit);
● Rückgabewert. Die Funktion gibt einen Zeiger auf eine Struktur vom Typ tm
zurück, in der Datum und Zeit abgelegt sind. Im Fehlerfall gibt die Funktion
einen NULL-Zeiger zurück.

Verwandte Funktionen
asctime(), ctime(), localtime(), time()

286
wctype.h

is..., isw.. <ctype.h><wctype.h>


Zeichenklassifizierung

Beschreibung
Die Funktionen aus der is...()-Gruppe überprüfen die Zugehörigkeit eines Zeichens zu
bestimmten Zeichengruppen. Die entsprechenden isw..()-Funktionen stellen die gleiche
Funktionalität für Wide Character-Zeichen zur Verfügung.
Name Testet auf
isalnum // Buchstaben und Ziffern (isalpha || isdigit)
isalpha // Buchstaben (A-Z, a-z) (isupper || islower)
iscntrl // Steuerzeichen (0x00-0x1f oder 0x7F).
isdigit // Ziffer (0-9).
isgraph // Ausgebbares Zeichen (0x21-0x7E) (isprint ohne isspace)
islower // Kleinbuchstabe (a-z).
isprint // Druckbares Zeichen (0x20-0x7E).
ispunct // Interpunktionszeichen (isprint ohne isspace und isalnum)
isspace // Whitespace-Zeichen (' ', '\f', '\n', '\r', '\t', '\v').
isupper // Großbuchstabe (A-Z).
isxdigit // Hexadezimalzahl (A-F, a-f, 0-9).

Parameter
int is...(int zeichen);
int isw...(wint_t widezeichen);
● Rückgabewert. Die Funktionen geben einen Wert ungleich Null (true) zurück,
wenn das übergebene Zeichen zu der von der Funktion überprüften Klasse von
Zeichen gehört.

Verwandte Funktionen
localeconv(), setlocale()

iswctype <wctype.h>
Wide Character-Klasse feststellen

Beschreibung
Testet, ob ein Zeichen einer bestimmten Klasse angehört. Die Klasse wird durch einen Aufruf
von wctype spezifiziert:
iswctype(wc, wctype("digit")) // = iswcdigit(wc)

Parameter
int iswctype(wint_t wc, wctype_t beschreibung);
● Rückgabewert. Liefert einen Wert ungleich Null, wenn das Wide Character-
Zeichen wc die beschriebene Eigenschaft hat.

287
Die C-Standardbibliothek

Verwandte Funktionen
wctype()

labs <stdlib.h>
Absolutwert einer long-Zahl bestimmen

Beschreibung
Die Funktion ermittelt den Betrag einer long-Ganzzahl und gibt ihn zurück. Der Betrag einer
Zahl ist ihr Abstand zu Null.

Parameter
long int labs(long int zahl);
● Rückgabewert. Betrag des Arguments.

Verwandte Funktionen
abs(), fabs()

ldexp <math.h>
Exponential berechnen

Beschreibung
ldexp berechnet den Wert von zahl*2^exp.

Parameter
double ldexp(double zahl, int exp);
● Rückgabewert. Liefert den Wert von zahl*2^exp; HUGE_VAL bei Überlauf.

Verwandte Funktionen
log(), log10(), pow()

ldiv <stdlib.h>
Quotient und Rest zweier long-Zahlen

Beschreibung
Die Funktion ldiv() teilt eine long-Ganzzahl durch eine andere und gibt das Ergebnis in Form
einer Struktur vom Typ ldiv_t zurück:

Parameter
ldiv_t ldiv(long int zahl1, long int zahl2);

288
wctype.h

● Rückgabewert. Die Funktion gibt eine Struktur vom Typ ldiv_t zurück, in der
sich der Quotient (.quot) und der Divisionsrest (.rem) befinden.

Verwandte Funktionen
div()

localeconv <locale.h>
Lokale Einstellung numerischer Formate

Beschreibung
Über die Funktion localeconv() können lokale Einstellungen zur Formatierung numerischer
Werte, insbesondere der Darstellung von Währungsangaben, abgefragt werden. Die Einstellun-
gen werden in einer lconv-Struktur abgelegt.

Parameter
struct lconv *localeconv(void);
● Rückgabewert. Zeiger auf die gefüllte Struktur lconv.

Verwandte Funktionen
setlocale()
Siehe Beispiel zu Header-Datei locale.h

localtime <time.h>
Uhrzeit auf Ortszeit einstellen

Beschreibung
Die Funktion wandelt die Kalenderzeit zeit in eine Struktur vom Typ tm um. Hierbei wird, im
Gegensatz zu der Funktion gmtime(), die Ortszeit berücksichtigt.

Parameter
struct tm *localtime(const time_t *zeit);
● Rückgabewert. Zeiger auf eine Struktur vom Typ tm oder einen NULL-Zeiger,
falls zeit nicht interpretiert werden konnte.

Verwandte Funktionen
asctime(), gmtime(), time()

log, log10 <math.h>


Logarithmus berechnen

289
Die C-Standardbibliothek

Beschreibung
Die Funktion log() berechnet den natürlichen Logarithmus ihres Arguments zur Basis e,
log10() den Logarithmus ihres Arguments zur Basis 10.

Parameter
double log(double x);
double log10(double x);
● Rückgabewert. Die Funktionen geben den jeweiligen Logarithmus von x zu-
rück. Da der Logarithmus nur für positive Werte größer Null definiert ist,
wird bei Werten von x < 0 EDOM in errno geschrieben; bei 0 als Argument wird
HUGE_VAL zurückgeliefert.

Verwandte Funktionen
exp(), pow()
Siehe Beispiel zu Header-Datei math.h

longjmp <setjmp.h>
Programmzustand wiederherstellen

Beschreibung
Mit der Funktion longjmp() wird die Umgebung wiederhergestellt, die beim Aufruf von set-
jmp() im Array umg gespeichert wurde. Die Ausführung wird danach nicht an der Stelle fortge-
führt, an der longjmp() aufgerufen wird, sondern dort, wo setjmp() aufgerufen wurde.

Parameter
void longjmp(jmp_buf umg, int wert);

Warnung
Die Funktion, in der der vorangehende Aufruf von setjmp() erfolgte, muß zum
Zeitpunkt des Sprungs durch longjmp() aktiv, d. h. auf dem Stack abgelegt sein.

Verwandte Funktionen
setjmp()
Siehe Beispiel zu Header-Datei setjmp.h

malloc <stdlib.h>
Speicherblock anfordern

290
wctype.h

Beschreibung
Die Funktion malloc() fordert einen Speicherblock von der übergebenen Größe an. Der von der
Funktion zurückgegebene Zeiger ist vom Typ *void und muß explizit in den gewünschten Typ
umgewandelt werden.

Parameter
void *malloc(size_t groesse);
● Rückgabewert. void-Zeiger auf den allokierten Speicherbereich oder NULL-
Zeiger, wenn Speicher nicht allokiert werden konnte.

Verwandte Funktionen
calloc(), free(), realloc()

mblen, mbrlen <stdlib.h><wchar.h>


Länge eines Multibyte-Zeichens

Beschreibung
Die Funktion mblen() ermittelt die Länge eines Multibyte-Zeichens. Die Funktion mbrlen()
ermittelt, nach wieviel Byte das Multibyte-Zeichen vollständig ist. Es werden maximal n Bytes
geprüft.

Parameter
int mblen(const char *mb, size_t n);
size_t mbrlen(const char *mb, size_t n, mbstate_t *ps);
● Rückgabewert. Die Funktion mblen() liefert die Anzahl der Bytes des Multiby-
te-Zeichens mb zurück. Handelt es sich um kein gültiges Multibyte-Zeichen,
wird ein negativer Wert zurückgegeben. Die Funktion mbrlen() liefert die An-
zahl der Bytes bis zum Abschluß des Multibyte-Zeichens mb zurück. Handelt es
sich um kein gültiges Multibyte-Zeichen oder tritt ein Fehler auf, wird ein ne-
gativer Wert zurückgegeben.

Verwandte Funktionen
mbstowcs(), mbtowc(), mbrtowc()

mbsinit <wchar.h>
Konvertierungsstatus abfragen

Beschreibung
Ermittelt, ob das mbstate_t-Objekt, auf das der Parameter verweist, einen anfänglichen Kon-
vertierungsstatus beschreibt.

291
Die C-Standardbibliothek

Parameter
int mbsinit(const mbstate_t *ps);
● Rückgabewert. Ein Wert ungleich Null zeigt an, daß ein NULL-Zeiger oder
ein Zeiger auf einen anfänglichen Konvertierungsstatus übergeben wurde; an-
sonsten wird Null zurückgeliefert.

Verwandte Funktionen
mbstowcs()

mbstowcs,mbsrtowcs <stdlib.h><wchar.h>
Konvertiert Multibyte-String

Beschreibung
Die Funktion mbstowcs() konvertiert den übergebenen Multibyte-String mb_string, der im
anfänglichen Shift-Status beginnt (der Zustand, in dem die Zeichen aus dem C-Zeichensatz 1:1
codiert sind), in ein Feld von Elementen des Typs wchar_t. Die Funktion mbsrtowcs() konver-
tiert einen Multibyte-String, der im durch ps gegebenen Konvertierungsmodus ist. Es werden
maximal n Wide Character-Zeichen eingelesen.

Parameter
size_t mbstowcs(wchar_t *wc, const char *mb_str, size_t n);
size_t mbsrtowcs(wchar_t *wc,const char *mb_str,size_t n,mbstate_t *ps);
● Rückgabewert. Liefert die Anzahl der umgewandelten Elemente zurück (ohne
mögliches Nullterminierungszeichen (\0)). Treten ungültige Multibyte-Sequen-
zen auf, wird ein negativer Wert zurückgegeben.

Verwandte Funktionen
mbstowcs(), mbtowc(), mbrtowc()

mbtowc,mbrtowc <stdlib.h><wchar.h>
Konvertiert Multibyte-Zeichen zu wchar_t

Beschreibung
Beide Funktionen konvertieren das übergebene Multibyte-Zeichen mb_char in eine Wide Cha-
racter-Repräsentation und speichern das Ergebnis in wc. Die Funktion mbtowc() bestimmt dabei
die Anzahl der Bytes in dem Multibyte-Zeichen, die Funktion mbrtowc() ermittelt, nach wieviel
Byte das Multibyte-Zeichen vollständig ist. Es werden maximal n Bytes konvertiert.

Parameter
int mbtowc(wchar_t *wc, const char *mb_char, size_t n);
size_t mbrtowc(wchar_t *wc,const char *mb, size_t n, mbstate_t *ps);

292
wctype.h

● Rückgabewert. Die Funktion mbtowc() liefert die Anzahl der Bytes des Multi-
byte-Zeichens mb zurück. Handelt es sich um kein gültiges Multibyte-Zeichen,
wird ein negativer Wert zurückgegeben. Die Funktion mbrtowc() liefert die An-
zahl der Bytes bis zum Abschluß des Multibyte-Zeichens mb zurück. Handelt es
sich um kein gültiges Multibyte-Zeichen oder tritt ein Fehler auf, wird ein ne-
gativer Wert zurückgegeben.

Verwandte Funktionen
mbstowcs(), mblen(), mbrtowc()

memchr, wmemchr <string.h><wchar.h>


Zeichen suchen

Beschreibung
Die Funktion untersucht einen Speicherbereich daraufhin, ob das übergebene Zeichen vor-
kommt. Die Suche schreitet so lange voran, bis entweder das Zeichen gefunden oder anzahl
Zeichen untersucht worden sind.

Parameter
C:
void *memchr(const void *puffer, int zeichen, size_t anzahl);
wchar_t *wmemchr(const wchar_t *puffer, wchar_t zeichen, size_t anzahl);
C++:
const void *memchr(const void *puffer, int zeichen, size_t anzahl);
const wchar_t *wmemchr(const wchar_t *puffer, wchar_t zeichen,
size_t anzahl);
void *memchr(void *puffer, int zeichen, size_t anzahl);
wchar_t *wmemchr(wchar_t *puffer, wchar_t zeichen, size_t anzahl);
● puffer. Anfangsadresse des zu durchsuchenden Speicherbereichs.
● zeichen. Das zu suchende Zeichen.
● anzahl. Maximal zu überprüfende Zeichen.
● Rückgabewert. Zeiger auf das gefundene Zeichen oder NULL-Zeiger.

Verwandte Funktionen
memcmp(), memset(), memcpy()

memcmp, wmemcmp <string.h><wchar.h>


Zeichen in Speicher vergleichen

293
Die C-Standardbibliothek

Beschreibung
Die Funktion vergleicht zeichenweise den Inhalt von puf1 mit dem von puf2. Der Vergleich wird
so lange durchgeführt, bis entweder ein Unterschied entdeckt oder die mit anzahl übergebene
Zeichenzahl überprüft wurde.

Parameter
int memcmp(const void *puf1, const void *puf2, size_t anzahl);
int wmemcmp(const wchar_t *puf1, const wchar_t *puf2, size_t anzahl);
● Rückgabewert. Die Funktion hat drei mögliche Rückgabewerte:

   
    
   

Verwandte Funktionen
strcmp(), strncmp()

memcpy, wmemcpy <string.h><wchar.h>


Zeichen zu Zwischenspeicher kopieren

Beschreibung
Die Funktion kopiert Zeichen von einem Speicherbereich in einen anderen. Es werden anzahl
Zeichen kopiert. (Beide Speicherbereiche dürfen sich nicht überlappen.)

Parameter
void *memcpy(void *ziel, const void *quelle, size_t anzahl);
wchar_t *wmemcpy(wchar_t *ziel, const wchar_t *quelle, size_t anzahl);
● Rückgabewert. Zeiger auf ziel.

Verwandte Funktionen
memchr(), memmove(), memset()

memmove, wmemmove <string.h><wchar.h>


Zwischenspeicher verlegen

Beschreibung
Diese Funktion kopiert den Inhalt eines Speicherbereichs in einen anderen (beide Speicherbe-
reiche dürfen sich überlappen). Es wird die als Argument übergebene Anzahl von Bytes kopiert.

294
wctype.h

Parameter
void *memmove(void *ziel, const void *quelle, size_t anzahl);
wchar_t *wmemmove(wchar_t *ziel, const wchar_t *, size_t anzahl);
● Rückgabewert. Zeiger auf ziel.

Verwandte Funktionen
memchr(), memchr(), memset()

memset, wmemset <string.h><wchar.h>


Zwischenspeicher beschreiben

Beschreibung
Die Funktion initialisiert einen Speicherbereich mit einem bestimmten Zeichen. Die Anzahl der
zu initialisierenden Speichereinheiten wird über das Argument anzahl festgelegt.
void *memset(void *puffer, int zeichen, size_t anzahl);
wchar_t *wmemset(wchar_t *puffer, int zeichen, size_t anzahl);
● Rückgabewert. Zeiger auf puffer.

Verwandte Funktionen
memchr(), memcmp(), memmove()

mktime <time.h>
Konvertiert Zeit von tm zu time_t

Beschreibung
Die Funktion mktime() konvertiert eine Zeitangabe, wie sie in der Struktur tm abgelegt ist, in
den Typ time_t.

Parameter
time_t mktime(struct tm *zeit);
● Rückgabewert. Die Funktion liefert die konvertierte Zeitangabe vom Typ
time_t zurück. Konnte die Zeitangabe nicht konvertiert werden, wird -1 zu-
rückgegeben.

Verwandte Funktionen
time(), gmtime(), localtime()

modf <math.h>
Gleitkommawert aufteilen

295
Die C-Standardbibliothek

Beschreibung
Die Funktion modf() teilt eine Gleitkommazahl wert in einen ganzzahligen Vorkomma-Anteil
und einen Nachkomma-Anteil auf.

Parameter
double modf(double wert, double *p_int);
● Rückgabewert. Der Nachkomma-Anteil wird zurückgegeben. Der Ganzzahlteil
wird an der Stelle gespeichert, auf die p_int zeigt.

Verwandte Funktionen
fmod(), frexp(), ldexp()

perror <stdio.h>
Fehlermeldung ausgeben

Beschreibung
Die Funktion perror() erzeugt eine Fehlermeldung, in dem sie den übergebenen String und die
Fehlermeldung, die dem derzeitigen Wert der Variablen errno entspricht, zusammenfügt und
dann an den Datenstream stderr ausgibt.

Parameter
void perror(const char *zkette);

Verwandte Funktionen
ferror(), clearerror(), strerror()

pow <math.h>
Potenz ermitteln

Beschreibung
Die Funktion berechnet x ^ y.

Parameter
double pow(double x, double y);
double pow(double x, int y);
● Rückgabewert. Bei erfolgreicher Ausführung liefert die Funktion die Potenz
von x hoch y zurück. Ist x < 0 und y keine ganzzahlige Zahl wird EDOM in errno
gschrieben; bei zu großem Ergebniswert wird HUGE_VAL zurückgeliefert

296
wctype.h

Verwandte Funktionen
sqrt()

printf, wprintf <stdio.h><wchar.h>


Formatierte Ausgabe an stdout

Beschreibung
Die Funktion gibt formatierte Daten an den Datenstream stdout aus. Zur Ausgabe wird eine
Formatzeichenkette untersucht. Normaler Text und Escape-Sequenzen in diesem String werden
einfach ausgegeben.
Findet printf() (wprintf()) in der Formatzeichenkette das Zeichen % mit einem
gültigen Formattyp und optionalen zusätzlichen Angaben, wird das zugehörige
wahlfreie Argument von printf() (wprintf()) in den angegebenen Typ umgewandelt
und in die Zeichenkette eingefügt.
Das allgemeine Format für die Typangabe sieht folgendermaßen aus:
% [Flag] [Breite] [Genauigkeit] [Typvorsatz] Formattyp
Die einzelnen Elemente der Typangabe und ihre Wirkung:
Formattyp Datentyp
c // Einzelnes Zeichen.
s // Nullzeichenterminierte Zeichenkette.
// Für wprintf() wird im Falle des Typvorsatzes l (siehe
// unten) die Wide Character-Zeichenkette in
// Multibyte-Zeichen umgewandelt.
d, i // Dezimale Ganzzahl.
u // Dezimale Ganzzahl ohne Vorzeichen.
o // Oktale Ganzzahl ohne Vorzeichen.
x // Hexadezimale Ganzzahl, ohne Vorzeichen und ohne Präfix
// (0x), Ausgabe mit Kleinbuchstaben.
X // Hexadezimale Ganzzahl, ohne Vorzeichen und ohne Präfix
// (0X), Ausgabe mit Großbuchstaben.
f // Gleitkommazahl, dezimale Schreibweise.
e,E // Gleitkommazahl, Exponential-Schreibweise:
// [-][Link]±xx bzw. [-][Link]±xx
g,G // Gleitkommazahl, die kürzeste Darstellung wird gewählt
// (f oder e).
p // Ausgabe als Zeiger.
n // Gibt die Anzahl der bis dahin ausgegebenen Zeichen aus.
% // Keine Konvertierung, das Zeichen % wird ausgegeben.
Folgende Zeichen können Sie als Flag verwenden, um das Formatelement zu erwei-
tern:
Flags Wirkung
- // Die Ausgabe erfolgt linksbündig. Wenn dieses Zeichen nicht
// angegeben wird, erfolgt die Ausgabe automatisch
// rechtsbündig, d.h., es werden Leerzeichen vorangestellt.

297
Die C-Standardbibliothek

+ // Bei numerischen Variablen erfolgt die Ausgabe mit Angabe


// eines Vorzeichens, d.h., bei positiven Zahlen wird der
// Ausgabe ein Pluszeichen vorangestellt. Die Ausgabe des
// Minuszeichens bei negativen Werten bleibt von diesem Flag
// unbeeinflußt.
Leerzeichen // Durch Angabe dieses Zeichens erreichen Sie bei positiven
// Zahlen, daß ihnen ein Leerzeichen vorangestellt wird.
0 // Füllt Feldbreite mit Nullen auf.
# // Die Wirkung des Formatzeichens # ist abhängig vom für das
// Argument festgelegten Formattyp.
● Wenn als Formattyp 0 (oktale Ganzzahl) angegeben wurde, wird der ausgege-
benen Variablen eine Null vorangestellt, sofern der Wert der Variablen nicht 0
beträgt.
● Bei den Formattypen für hexadezimale Ganzzahlen (x und X) wird der Ausgabe
0x bzw. 0X vorangestellt.
● Bei den Formattypen e, E und f (Gleitkommazahlen) wird durch # die Ausga-
be eines Dezimalpunktes erzwungen.
● Die Wirkung bei den Formattypen g und G ist der bei e und E identisch.
Breite
In diesem Feld kann die minimale Anzahl der auszugebenden Zeichen festgelegt
werden. Wenn die Zahl der auszugebenden Zeichen kleiner ist, als der in [Breite]
angegebene Wert, werden (je nachdem ob das – Flag gesetzt wurde) links oder
rechts Leerzeichen ausgegeben, bis der in [Breite] angegebene Wert erreicht ist. Ist
der Zahl eine Null vorangestellt, werden anstelle der Leerzeichen Nullen hinzu-
gefügt.
Genauigkeit
Der Angabe der Genauigkeit, mit der die Anzahl der auszugebenden Dezimalstellen
festgelegt wird, muß ein Punkt vorangestellt werden. So können die Parameter
Breite und Genauigkeit voneinander unterschieden werden. Die Wirkung des Wer-
tes für die Genauigkeit ist vom auszugebenden Datentyp abhängig.
Genauigkeit
Zeichen Wirkung
d,i,u,o,x,X // Der Wert für Genauigkeit gibt die Minimalzahl der
// Ziffern an, die ausgegeben werden.
e,E,f // Gibt die Anzahl der Ziffern an, die nach dem
// Dezimalpunkt ausgegeben werden. Die letzte Zahl wird
// gerundet.
g,G // Die durch Genauigkeit angegebene Zahl von signifikanten
// Stellen wird ausgegeben.
c // Keine Wirkung. Das Zeichen wird ausgegeben.
s // Der Wert gibt die Maximalzahl der Zeichen an, die
// ausgegeben werden.

298
wctype.h

Vor dem Formattyp können verschiedene Typvorsätze stehen, die Angaben über
die Größe des Parameters machen.
Typvorsatz Bedeutung
h // Wenn als Formattyp d, i, o, x oder X angegeben wird, ist
// der Parameter vom Typ short int. Beim Formattyp u wird
// mit dem Typvorsatz h eine Variable vom Typ short unsigned
// int erwartet.
l // Bei den Formattypen d, i, o, x oder X wird ein Parameter
// vom Typ long int, bei u vom Typ long unsigned int
// erwartet.
// Bei den Formattypen e, E, f, g, und G wird eine Variable
// des Typs double anstelle von float erwartet.
// Für wprintf() wird für einen c-Parameter ein
// wint_t- statt eines int-Arguments und für einen
// s-Parameter ein wchar_t-Zeiger statt eines char-Zeigers
// erwartet. Zudem wird die automatische Konvertierung von
// Wide Character in Multibyte eingeschaltet.
L // Bei den Formattypen e, E, f, g, und G wird eine Variable
// des Typs long double erwartet.
// Für wprintf() wird für einen s-Parameter ein
// wchar_t-Zeiger statt eines char-Zeigers als Argument
// erwartet.
Die nachstehenden Escape-Sequenzen werden von der Funktion printf() (wprintf())
wie folgt umgewandelt:
Sequenz Wirkung
\a // Signalton.
\v // Vertikaltabulator.
\b // Rückschritt.
\' // Apostroph.
\f // Seitenvorschub.
\" // Anführungszeichen.
\n // Neue Zeile.
\\ // Schrägstrich links.
\r // Wagenrücklauf.
\ddd // ASCII-Zeichen in Oktal-Schreibweise.
\t // Horizontaltabulator.
\xdd // ASCII-Zeichen in Hexadezimal-Schreibweise.

Parameter
int printf(const char *format,...);
int wprintf(const wchar_t *format,...);
● Rückgabewert. Anzahl der ausgegebenen Zeichen.

Verwandte Funktionen
sprintf(), vsprintf()
Siehe Praxisteil, Kategorie Ein- und Ausgabe, Formatierte Ein- und Ausgabe in C

299
Die C-Standardbibliothek

putc, putwc <stdio.h><wchar.h>


Zeichen in Stream schreiben

Beschreibung
Die Funktion schreibt ein einzelnes Zeichen in einen Stream.

Parameter
int putc(int zeichen, FILE *stream);
wint_t putwc(wchar_t zeichen, FILE *stream);
● Rückgabewert. Die Funktion gibt das geschriebene Zeichen zurück. Der Rück-
gabewert EOF (WEOF) deutet auf einen Fehler oder das Ende der Datei hin.

Verwandte Funktionen
putchar(), printf(), puts()

putchar, putwchar <stdio.h><wchar.h>


Zeichenausgabe an stdout

Beschreibung
Die Funktion schreibt ein einzelnes Zeichen an den Datenstream stdout. Es entspricht somit
dem Aufruf von putc(zeichen,stdout), bzw. putwc(zeichen,stdout).

Parameter
int putchar(int zeichen);
wint_t putwchar(wchar_t zeichen);
● Rückgabewert. Die Funktion gibt das ausgegebene Zeichen zurück. Im Fehler-
fall ist der Rückgabewert EOF (WEOF).

Verwandte Funktionen
putc(), printf(), puts()

puts <stdio.h>
Zeichenkette an stdout schreiben

Beschreibung
Die Funktion puts() schreibt eine Zeichenkette an den Datenstream stdout. Das Nullterminie-
rungszeichen (\0) des Strings wird durch das Zeilenvorschubzeichen (\n) ersetzt.

Parameter
int puts(const char *zkette);

300
wctype.h

● Rückgabewert. Bei fehlerfreier Ausführung wird ein nicht-negativer Wert zu-


rückgeliefert, ansonsten EOF.

Verwandte Funktionen
fputs(), gets()

qsort <stdlib.h>
Quicksort ausführen

Beschreibung
Mit der Funktion qsort() kann ein Datenfeld sortiert werden. Die Funktion verwendet dazu den
QuickSort-Algorithmus. Der beim Sortieren notwendige Vergleich wird durch eine Funktion
durchgeführt, deren Adresse an qsort() übergeben wird. Diese Funktion muß zwei Elemente
miteinander vergleichen und folgende Werte an qsort() zurückgeben:
negativ Das erste Element ist kleiner als das zweite.
Null Beide Elemente sind identisch.
positiv Das erste Element ist größer als das zweite.

Parameter
void qsort (void *basis, size_t anzahl, size_t laenge,
int (*vgl)(const void *elem1, const void *elem2));
● basis. Zeiger auf Anfang des Arrays.
● anzahl. Anzahl der Array-Elemente.
● laenge. Größe jedes Elementes in Bytes.
● vgl. Zeiger auf Funktion, die zwei Elemente vom Typ const void* vergleicht.

Verwandte Funktionen
bsearch()

raise <signal.h>
Signal an ausführendes Programm

Beschreibung
Die Funktion raise() sendet ein Signal an das aufrufende Programm. Über die Funktion
signal() ist es möglich, eigene Routinen einzurichten, die nach der Auslösung eines Signals
aufgerufen werden. Für das zu erzeugende Signal (und somit für das Argument sig) können die
symbolischen Konstanten SIG... (siehe Header signal.h) verwendet werden.

Parameter
int raise(int sig);

301
Die C-Standardbibliothek

● Rückgabewert. Null, bei erfolgreicher Ausführung.

Verwandte Funktionen
abort(), signal()

rand <stdlib.h>
Pseudo-Zufallszahl generieren

Beschreibung
Die Funktion rand() erzeugt eine Pseudo-Zufallszahl. Die erzeugte Zahl liegt im Bereich von 0
bis RAND_MAX. Die Funktion generiert immer die gleiche Folge von Zufallszahlen, es sei denn,
Sie ändern den Anfangswert mit der Funktion srand(). Der Aufruf von rand() ohne den vorhe-
rigen Aufruf von srand() hat die gleiche Wirkung, wie wenn vorher srand() mit dem Argument
1 aufgerufen worden ist.

Parameter
int rand(void);
● Rückgabewert. Erzeugte Pseudo-Zufallszahl.

Verwandte Funktionen
srand()

realloc <stdlib.h>
Speicherblock neu zuordnen

Beschreibung
Mit der Funktion realloc() kann die Größe eines zuvor mit malloc() oder calloc() angefor-
derten Speicherblocks angepaßt werden. Der Inhalt des alten Speicherblocks bleibt dabei
erhalten, seine Adresse kann sich jedoch ändern.

Parameter
void *realloc(void *puffer, size_t groesse);
● puffer. Zeiger auf den zu vergrößernden oder verkleinernden Speicherblock.
● groesse. Neue Größe für den Speicherblock.
● Rückgabewert. Die Funktion gibt einen Zeiger zum neu zugeordneten Spei-
cherblock zurück oder einen NULL-Zeiger, wenn der Speicher nicht eingerich-
tet werden konnte.

Verwandte Funktionen
calloc(), free(), malloc()

302
wctype.h

remove <stdio.h>
Datei löschen

Beschreibung
Die Funktion remove() löscht die Datei (sofern Schreibrecht besteht), deren Name ihr überge-
ben wurde. Die Datei sollte dazu geschlossen sein.

Parameter
int remove(const char *dateiname);
● Rückgabewert. Die Funktion gibt eine Null zurück, wenn die Datei gelöscht
wurde, sonst einen Wert ungleich 0.

Verwandte Funktionen
rename(), tmpfile(), tmpnam()

rename <stdio.h>
Datei umbenennen

Beschreibung
Die Funktion rename() ändert einen Dateinamen von altname in neuname. Beide Argumente
müssen einen gültigen Pfadnamen beinhalten.

Parameter
int rename(const char *altname, const char *neuname);
● Rückgabewert. Die Funktion gibt eine Null zurück, wenn die Datei umbe-
nannt werden konnte, sonst einen Wert ungleich 0.

Verwandte Funktionen
remove(), tmpfile(), tmpnam()

rewind <stdio.h>
Streampositionszeiger zum Anfang

Beschreibung
Die Funktion rewind() setzt die Dateipositionsanzeige auf den Anfang der Datei und löscht
eventuell gesetzte Fehlerflags. Die Funktion entspricht damit den Aufrufen:
fseek(stream, 0L, SEEK_SET);
clearerr(stream);

Parameter
void rewind(FILE *stream);

303
Die C-Standardbibliothek

Verwandte Funktionen
fseek(), ftell()

scanf, wscanf <stdio.h><wchar.h>


Formatierte Daten von stdin lesen

Beschreibung
Die Funktion liest formatierte Daten vom Datenstream stdin. Sie benutzt das Argument format,
um die eingelesenen Zeichen in die richtigen Datentypen umzuwandeln. Die eingelesenen
Daten werden dann an die Speicherstellen geschrieben, die mit den weiteren Funktionsargu-
menten übergeben werden. Für jedes weitere Funktionsargument muß in der Formatzeichen-
kette ein Typbezeichner angegeben worden sein.
Typbezeichner besitzen folgendes allgemeine Format, wobei die Angaben in eckigen
Klammern optional sind:
%[*][Breite][Größe]Typ
● %: Markiert den Anfang eines Typbezeichners. Das Prozentzeichen und der
Typ sind die Elemente, aus denen jeder Typbezeichner mindestens zusammen-
gesetzt sein muß.
● *: Steht nach dem Prozentzeichen ein Stern (*), wird die Zuweisung des näch-
sten Eingabefeldes unterdrückt.
● Breite: Die Breite ist eine positive Dezimal-Ganzzahl, mit der die maximal zu
lesenden Zeichen angegeben werden.
● Größe: Dieses Feld im Typbezeichner kann verwendet werden, um die Größe
der Variablen anzugeben.
● Typ:
Formattyp Datentyp
c // Einzelnes Zeichen.
s // Zeichenkette.
// Ist der Typvorsatz l gesetzt (siehe oben), werden
// eingelesene Multibyte-Zeichenfolge in Wide Characters
// umgewandelt.
d // Dezimale Ganzzahl.
i // Dezimale, oktale (0) oder hexadezimale (0x, 0X) Ganzzahl.
u // Dezimale Ganzzahl ohne Vorzeichen.
o // Oktale Ganzzahl ohne Vorzeichen.
x // Hexadezimale Ganzzahl, ohne Vorzeichen und ohne Präfix
// (0x), Ausgabe der Kleinbuchstaben.
f // Gleitkommazahl, dezimale Schreibweise.
e,E // Gleitkommazahl, Exponential-Schreibweise:
// [-][Link]±xx bzw. [-][Link]±xx
g,G // Gleitkommazahl, die kürzeste Darstellung wird gewählt
// (f oder e).
p // Zeiger.

304
wctype.h

n // Gibt die Anzahl der bis dahin eingelesenen Zeichen aus.


[...] // Entspricht der längsten Zeichenkette, die nur aus den in
// den Klammern spezifizierten Zeichen besteht.
// Ist der Typvorsatz l gesetzt (siehe oben), werden
// eingelesene Multibyte-Zeichenfolge in Wide Characters
// umgewandelt.
[^...] // Entspricht der längsten Zeichenkette, die keines der in
// den Klammern spezifizierten Zeichen enthält.
// Ist der Typvorsatz l gesetzt (siehe oben), werden
// eingelesene Multibyte-Zeichenfolge in Wide Characters
// umgewandelt.
% // Keine Konvertierung, das Zeichen % wird eingelesen.
Den Typangaben können zur näheren Spezifizierung folgende Typvorsätze voran-
gestellt werden:
Typvorsatz Bedeutung
h // Wenn als Formattyp d, i, n, o, u, x angegeben wird, ist
// das Argument vom Typ short int.
l // Wenn als Formattyp d, i, n, o, u, x angegeben wird, ist
// das Argument vom Typ long int.
// Bei den Formattypen e, E, f, g, und G wird ein Argument
// des Typs double anstelle von float erwartet.
// Für wscanf(): Bei den Formattypen c, s und [ ] wird ein
// Argument des Typs wchar_t erwartet und die automatische
// Konvertierung von Multibyte zu Wide Character
// eingeschaltet.
L // Bei den Formattypen e, E, f, g, und G wird ein Argument
// des Typs long double erwartet.

Parameter
int scanf(const char *format, ...);
int wscanf(const wchar_t *format, ...);
● Rückgabewert. Die Funktion gibt die Anzahl der umgewandelten und eingele-
senen Felder zurück (kann auch 0 sein) oder EOF (WEOF), wenn versucht wurde,
das Ende der Zeichenkette zu lesen, oder ein Fehler aufgetreten ist.

Verwandte Funktionen
fscanf(), printf(), sscanf(), vsprintf()

setbuf <stdio.h>
Stream-Puffer

Beschreibung
Mit der Funktion setbuf() kann für die Zwischenspeicherung eines Streams ein eigener Puffer
eingerichtet werden, der den automatisch zugeordneten Puffer ersetzt. Dazu muß das Funkti-

305
Die C-Standardbibliothek

onsargument puffer auf einen Speicherbereich zeigen, der mindestens BUFSIZ Bytes groß ist. Ist
das Argument ein NULL-Zeiger, wird keine Zwischenspeicherung durchgeführt.

Parameter
void setbuf(FILE *stream, char *puffer);

Verwandte Funktionen
setvbuf()

setjmp <setjmp.h>
Programmstatus speichern

Beschreibung
Die Funktion setjmp() dient zur Vorbereitung eines nicht lokalen Sprungs (aus einer Funktion
heraus). Alle wichtigen Informationen zum späteren Rücksprung an die aktuelle Stelle werden
in den Puffer umg gespeichet.

Parameter
int setjmp(jmp_buf umg);
● Rückgabewert. Nach dem Sichern der Umgebung ist der Rückgabewert 0.
Nach einem späteren longjmp()-Aufruf liefert die Funktion einen Wert ungleich
0, um eine Endlosschleife zu vermeiden:

Verwandte Funktionen
longjmp()
Siehe Beispiel zu Header-Datei setjmp.h

setlocale <locale.h>
Ändern einer Locale-Einstellung

Beschreibung
Mit dieser Funktion kann die lokale Einstellung zu dem verwendeten Zeichensatz, den Wäh-
rungsangaben, etc. abgefragt oder gewechselt werden. Dem ersten Parameter können die LC...-
Konstanten (siehe Header-Datei locale.h) übergeben werden, um auszuwählen, welche Kate-
gorien von den Änderungen betroffen sein sollen. Der zweite Parameter zeigt auf den Namen
der lokalen Einstellung, die für die angegebenen Kategorien eingerichtet werden soll (bei-
spielsweise "C" für die minimale Umgebung oder "" für die Systemumgebung).
Wird an den Parameter lokale ein NULL-Zeiger übergeben, wird ein String für die
Kategorie der aktuellen lokalen Einstellungen zurückgeliefert.

306
wctype.h

Parameter
char *setlocale(int kategorie, char *lokale);
● kategorie. Eine der LC-Konstanten aus locale.h zur Auswahl eines Teilgebiets
der lokalen Einstellungen.
● lokale. Name der Lokale.
● Rückgabewert. Bei Erfolg gibt die Funktion einen Zeiger auf den String mit
den Kategorien und Einstellungen zurück. Im Fehlerfall wird ein NULL-Zeiger
zurückgeliefert, und die Locale-Einstellung bleibt unverändert.

Verwandte Funktionen
localeconv()

setvbuf <stdio.h>
Stream-Pufferung

Beschreibung
Mit der Funktion setvbuf() kann die Zwischenspeicherung für einen Stream festgelegt werden.
Gegenüber der Funktion setbuf() haben Sie hier mehr Einstellmöglichkeiten.

Parameter
int setvbuf(FILE *stream, char *buffer,
int buf_typ, size_t buf_groesse);
● stream. Stream, für den Puffer gesetzt werden soll.
● buffer. Nullzeiger (der Puffer wird von setvbuf eingerichtet) oder Zeiger auf
selbst allokierten Puffer.
● buf_typ. Kann den Wert einer von drei symbolischen Konstanten annehmen,
die in der Datei <stdio.h> definiert sind. Wenn das Argument buf_typ den
Wert _IONBF besitzt, werden die Optionen buffer und buf_groesse ignoriert und
die Flags des Streams auf diesen Modus eingestellt. Bei den beiden anderen
Werten wird zuerst der Wert des Arguments buffer überprüft. Steht dort ein
NULL-Zeiger, allokiert die Funktion einen Zwischenspeicher von der Größe,
die in buf_groesse angegeben ist. Anderenfalls sollte buffer auf einen Speicher-
bereich zeigen, der von Ihnen in buf_groesse Bytes allokiert wurde.
_IOFBF Zeigt an, daß ein Stream voll gepuffert werden soll. Das bedeutet, daß so
lange Daten im Zwischenspeicher abgelegt werden, bis er voll ist.
_IOLBF Stream wird zeilenweise gepuffert.
_IONBF Stream wird nicht gepuffert.

● buf_groesse. Größe des Puffers.

307
Die C-Standardbibliothek

● Rückgabewert. Bei Erfolg gibt die Funktion eine Null zurück. Im Fehlerfall
oder bei ungültigen Parametern ist der Rückgabewert ungleich Null.

Warnung
Die Funktion muß aufgerufen werden, nachdem der Stream mit einer geöffneten
Datei verbunden wurde und bevor irgendwelche Operationen auf dem Stream aus-
geführt wurden.

Verwandte Funktionen
setbuf()

signal <signal.h>
Unterbrechungssignal-Handhabung

Beschreibung
Mit der Funktion signal() können Bearbeitungsroutinen festgelegt werden, die immer dann
aufgerufen werden, wenn ein bestimmtes Signal auftritt.

Parameter
void (*signal(int sig, void(*funkt)(int)))(int);
● sig. Die Funktion erhält als erstes Argument eine SIG..-Konstante (siehe Hea-
der-Datei signal.h), die das Signal beschreibt, dessen Behandlung geändert
werden soll.
● funkt. Das zweite Argument ist ein Zeiger auf eine Funktion, die keinen Wert
zurückgibt, jedoch die Nummer des Signals erhält. Ruft diese Bearbeitungs-
funktion irgendeine Funktion der C-Laufzeitbibliothek außer signal() auf, ist
das Verhalten implementierungsspezifisch. Statt eines Funktionszeigers kön-
nen auch folgende Konstanten benutzt werden:
SIG_DFL Bezeichnet die Standardbearbeitung.
SIG_IGN Signal ignorieren. Das Unterbrechungssignal wird ignoriert. Diese Kon-
stante sollte nicht gemeinsam mit SIGFPE eingesetzt werden, da dies das
Fließkomma-Arithmetik-Paket unbrauchbar macht.
SIG_ERR Wird benutzt, um eine Fehlerbedingung bei der Ausführung anzuzeigen.

● Rückgabewert. Im Erfolgsfall gibt die Funktion die Adresse der vorherigen Be-
handlungsroutine für die Signale des angegebenen Typs zurück. Im Fehlerfall
wird der Wert der Konstanten SIG_ERR zurückgegeben und die globale Variable
errno auf einen positiven Wert gesetzt.

308
wctype.h

Verwandte Funktionen
raise()
Siehe Beispiel zu Header-Datei signal.h

sin, sinh <math.h>


Sinus berechnen

Beschreibung
Die Funktion sin() berechnet den Sinus, sinh() den Sinus hyperbolicus ihres Arguments.

Parameter
double sin(double x);
double sinh(double x);
● Rückgabewert. sin() liefert den Sinus des Arguments im Bereich [-1, 1].
sinh() liefert den Sinus hyperbolicus des Arguments im Bereich [-8 , 8 ].

Warnung
Der Sinus hyperbolicus steigt und fällt sehr schnell.

Verwandte Funktionen
asin(), cos(), cosh()
Siehe Beispiel zu Header-Datei math.h

sprintf, swprintf <stdio.h><wchar.h>


Formatierte Daten in String schreiben

Beschreibung
Die Funktion nimmt eine formatierte Ausgabe in eine Zeichenkette vor. Die Formatzeichenkette
hat den für printf() beschriebenen Aufbau.

Parameter
int sprintf(char *zkette, const char *format, ...);
int swprintf(wchar_t *zkette, size_t n, const wchar_t *format, ...);
● zkette. Zeiger auf String, in den Ausgabe erfolgen soll.
● n. Maximale Anzahl an Zeichen, die geschrieben werden (nur für swprintf()).
● format. Formatzeichenkette (siehe printf()).
● .... Variable Anzahl von Argumenten.
● Rückgabewert. Die Funktion gibt die Anzahl der ausgegebenen Zeichen zu-
rück, ohne die abschließende Null. Im Fehlerfall wird EOF (WEOF) zurückgelie-
fert.

309
Die C-Standardbibliothek

Verwandte Funktionen
printf(), sscanf(), vprintf(), vsprintf()

sqrt <math.h>
Quadratwurzel berechnen

Beschreibung
Die Funktion sqrt() berechnet die Quadratwurzel ihres Arguments und gibt diesen Wert
zurück.

Parameter
double sqrt(double zahl);
● Rückgabewert. Quadratwurzel des Arguments. Da die Wurzel nur für positive
Werte größer Null definiert ist, wird bei Werten von x < 0 EDOM in errno ge-
schrieben.

Verwandte Funktionen
pow()

srand <stdlib.h>
Zufallszahlengenerator initialisieren

Beschreibung
Die Funktion srand() verwendet ihr Argument, um den Startpunkt einer Reihe von Zufallszah-
len festzulegen, die dann von rand() zurückgegeben werden. Wird die Funktion zweimal mit
dem gleichen Wert aufgerufen, erzeugt sie die gleiche Folge von Zufallszahlen.

Parameter
void srand(unsigned int zahl);

Verwandte Funktionen
rand()

sscanf, swscanf <stdio.h><wchar.h>


Formatierte Daten aus String einlesen

Beschreibung
Die Funktion liest formatierte Daten aus einem String ein. Sie verwendet die Formatzeichen-
kette, um die eingelesenen Daten in die richtigen Typen umzuwandeln. Die weiteren wahlfreien
Argumente müssen Adressen sein, an die die eingelesenen Daten geschrieben werden sollen.

310
wctype.h

Die Formatzeichenkette kann das gleiche Muster enthalten, wie unter scanf()
beschrieben.

Parameter
int sscanf(const char *str, const char *format, ...);
int swscanf(const wchar_t *str, const wchar_t *format, ...);
● puffer. Zeiger auf String, aus dem die Daten ausgelesen werden.
● format. Formatierungsstring (siehe scanf()).
● Rückgabewert. Die Funktion gibt die Anzahl der umgewandelten und eingele-
senen Felder zurück oder EOF (WEOF), wenn versucht wurde, das Ende der Zei-
chenkette zu lesen.

Verwandte Funktionen
fscanf(), scanf(), sprintf()

strcat, wcscat <string.h><wchar.h>


Zeichenkette anhängen

Beschreibung
Die Funktion kopiert alle Zeichen des Strings, auf den quelle zeigt (inklusive des den String
beendenden \0-Zeichens), an das Ende der Zeichenkette, auf die ziel zeigt. Das Terminations-
zeichen des ersten Strings wird überschrieben.

Parameter
char *strcat(char * ziel, const char * quelle);
wchar_t *wcscat(wchar_t * ziel, const wchar_t * quelle);
● Rückgabewert. Zeiger auf die verbundene Zeichenkette.

Verwandte Funktionen
strncat(), strcpy(), strspn()
Siehe Praxisteil, Kategorie Zeichenketten, Programmieren mit C-Strings

strchr, wcschr <string.h><wchar.h>


Zeichen in String finden

Beschreibung
Die Funktion sucht nach dem ersten Vorkommen eines Zeichens in einer Zeichenkette. Das
Nullterminierungszeichen am Ende der Zeichenkette ist in die Suche eingeschlossen.

311
Die C-Standardbibliothek

Parameter
C:
char *strchr(const char *zkette, int zeichen);
wchar_t *wcschr(const wchar_t *zkette, wchar_t zeichen);
C++:
const char *strchr(const char *zkette, int zeichen);
const wchar_T *wcschr(const wchar_t *zkette, wchar_t zeichen);
char *strchr(char *zkette, int zeichen);
wchar_t *wcschr(wchar_t *zkette, wchar_t zeichen);
● Rückgabewert. Die Funktion gibt einen Zeiger auf zeichen zurück, wenn es ge-
funden wurde, anderenfalls einen NULL-Zeiger.

Verwandte Funktionen
strrchr(), strcspn(), strpbrk(), strspn()

strcmp, wcscmp <string.h><wchar.h>


Zeichenketten vergleichen

Beschreibung
Die Funktion vergleicht jedes Zeichen von zkette1 mit dem Zeichen an der korrespondierenden
Position von zkette2. Der Vergleich wird so lange fortgeführt, bis entweder zwei unterschiedli-
che Zeichen gefunden oder das Ende der Zeichenkette erreicht wurde.

Parameter
int strcmp(const char *zkette1, const char *zkette2);
int wcscmp(const wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Die Funktion hat drei mögliche Rückgabewerte, in denen das
Ergebnis des Vergleichs kodiert ist:
< 0 zkette1 < zkette2
0 zkette1 == zkette2
> 0 zkette1 > zkette2

Verwandte Funktionen
strncmp(), strcoll()

strcoll, wcscoll <string.h><wchar.h>


Zeichenkette kopieren

Beschreibung
Die Funktion vergleicht den String zkette1 mit dem String zkette2 nach den lokalen Einstel-
lungen der Kategorie LC_COLLATE.

312
wctype.h

Parameter
int strcoll(const char *zkette1, const char *zkette2);
int wcscoll(const wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Die Funktion hat drei mögliche Rückgabewerte, in denen das
Ergebnis des Vergleichs kodiert ist:
< 0 zkette1 < zkette2
0 zkette1 == zkette2
> 0 zkette1 > zkette2

Verwandte Funktionen
strcmp()

strcpy, wcscpy <string.h><wchar.h>


Zeichenkette kopieren

Beschreibung
Die Funktion kopiert alle Zeichen der Zeichenkette quelle (inklusive des beendenden Nullter-
minierungszeichens) in den Speicherbereich, auf den ziel zeigt. Das Verhalten der Funktion ist
nicht definiert, wenn der Speicherbereich, auf den ziel zeigt, vom Speicherbereich überlappt
wird, auf den quelle zeigt.

Parameter
char *strcpy(char *ziel, const char *quelle);
wchar_t *wcscpy(wchar_t *ziel, const wchar_t *quelle);
● Rückgabewert. Zeiger auf die ziel-Zeichenkette.

Verwandte Funktionen
strncpy()

strcspn, wcscspn <string.h><wchar.h>


Präfix in String

Beschreibung
Die Funktion bestimmt die Länge des vorangehenden Teil-Strings von zkette1, der keine Zei-
chen aus zkette2 enthält.

Parameter
size_t strcspn(const char *zkette1,const char *zkette2);
size_t wcscspn(const wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Länge des gefundenen Präfix von zkette1.

313
Die C-Standardbibliothek

Verwandte Funktionen
strspn(), strncmp()

strerror <string.h>
System-Fehlermeldung holen

Beschreibung
Die Funktion strerror() dient der Unterstützung beim Generieren von Fehlermeldungen. Übli-
cherweise erhält sie als Argument die globale Variable errno, die von einigen Funktionen der
Laufzeitbibliothek gesetzt wird, wenn bei der Abarbeitung der entsprechenden Funktion ein
Fehler auftrat. Die Funktion strerror() schreibt die zu dem Wert von fehler gehörende Feh-
lermeldung in einen statischen Puffer und liefert einen Zeiger auf diesen Puffer zurück.
Eine Ausgabe der Fehlermeldung erfolgt mit dieser Funktion nicht.

Parameter
char *strerror(int fehler);
● Rückgabewert. Zeiger auf die Fehlermeldung, die dem Argument fehler ent-
spricht.

Verwandte Funktionen
perror()

strftime, wcsftime <time.h><wchar.h>


Formatiert die Uhrzeit

Beschreibung
Die Funktion übernimmt die Zeitangabe aus der Variablen zeit der Struktur tm, konvertiert sie
entsprechend der in dem Parameter format enthaltenen Formatierungsanweisungen und der
lokalen Einstellung (LC_TIME) und gibt sie in die Zeichenkette str aus.
Folgende Formatierungsangaben sind für den Parameter format zulässig:
%% // Prozentzeichen %.
%a // Abgekürzter Name des Wochentags.
%A // Voller Name des Wochentags.
%b // Abgekürzter Name des Monats.
%B // Voller Name des Monats.
%c // Datum und Zeit.
%d // Tag des Monats (01 – 31).
%H // Stunde (00 -23).
%I // Stunde (01 – 12).
%j // Tag des Jahres (001 – 366).
%m // Monat (01 – 12).
%M // Minute (00 – 59).
%p // AM oder PM.

314
wctype.h

%S // Sekunde (00 – 59).


%U // Wochennummer (00 – 53), Woche beginnt mit Sonntag.
%w // Wochentag (0 – 6), Sonntag == 0.
%W // Wochennummer (00 – 53), Woche beginnt mit Montag.
%x // Datum.
%X // Uhrzeit.
%y // Jahr ohne Jahrhundertangabe (00 – 99).
%Y // Jahr mit Jahrhundertangabe.
%Z // Name der Zeitzone.

Parameter
size_t strftime(char *str, size_t maxsize,
const char *format, const struct tm *zeit);
size_t wcsftime(wchar_t *str, size_t maxsize,
const wchar_t *format, const struct tm *zeit);
● str. Ausgabe-String, in den die umformatierte Datums/Zeitangabe geschrieben
wird..
● maxsize. Maximale Anzahl von Zeichen, die in str geschrieben werden dürfen.
● format. Formatierungs-String, der aus oben aufgeführten Formatierungsanwei-
sungen bestehen kann.
● zeit. Umzuformatierende Datum/Zeitangabe.
● Rückgabewert. Die Funktion liefert die Anzahl, der nach str geschriebenen
Zeichen zurück. Werden mehr Zeichen benötigt, als durch maxsize freigestellt,
wird Null zurückgeliefert. Die konvertierte Zeitangabe wird über den Parame-
ter str zur Verfügung gestellt.

Verwandte Funktionen
localtime(), time(), gmtime(), setlocale()

strlen, wcslen <string.h><wchar.h>


Länge einer Zeichenkette ermitteln

Beschreibung
Die Funktion ermittelt die Länge der übergebenen Zeichenkette. Das den String beendende
Nullterminierungszeichen wird nicht mitgezählt.

Parameter
size_t strlen(const char *zkette);
size_t wcslen(const wchar_t *zkette);
● Rückgabewert. Länge der Zeichenkette (ohne Nullterminierungszeichen).

315
Die C-Standardbibliothek

Verwandte Funktionen
strcpy(), sizeof-Operator

strncat, wcsncat <string.h><wchar.h>


n Zeichen an String anhängen

Beschreibung
Die Funktion kopiert anzahl Zeichen des Strings, auf den quelle zeigt, an das Ende des Strings,
auf den ziel zeigt. Das Kopieren wird beendet, wenn entweder anzahl Zeichen übertragen oder
das Ende von ziel erreicht wurde.

Parameter
char *strncat(char * ziel, const char *quelle, size_t anzahl);
wchar_t *wcsncat(wchar_t * ziel, const wchar_t *quelle, size_t anzahl);
● Rückgabewert. Zeiger auf ziel.

Verwandte Funktionen
strcat(), strncpy()

strncmp, wcsncmp <string.h><wchar.h>


n Zeichen in Strings vergleichen

Beschreibung
Die Funktion vergleicht die ersten anzahl Zeichen der Strings zkette1 und zkette2. Der Ver-
gleich endet, wenn entweder ein Nullterminierungszeichen eingelesen wird oder ein Zeichen-
paar gefunden wurde, das nicht identisch ist.

Parameter
int strncmp (const char *zkette1, const char *zkette2, size_t anzahl);
int wcsncmp (const wchar_t *zkette1, const wchar_t *zkette2,
size_t anzahl);
● Rückgabewert. Die Funktion hat drei mögliche Rückgabewerte, in denen das
Ergebnis des Vergleichs kodiert ist:
< 0 zkette1 < zkette2
0 zkette1 == zkette2
> 0 zkette1 > zkette2

Verwandte Funktionen
strcmp(), strcoll()

316
wctype.h

strncpy, wcsncpy <string.h><wchar.h>


n Zeichen aus String kopieren

Beschreibung
Die Funktion kopiert anzahl Zeichen aus dem Speicherbereich, auf den quelle zeigt, in den
Speicherbereich, auf den ziel zeigt. Wenn quelle weniger als anzahl Zeichen besitzt, wird so
lange das Nullterminierungszeichen kopiert, bis anzahl Zeichen geschrieben wurde.
Der Speicherbereich, auf den ziel zeigt, muß anzahl Zeichen groß sein. Anderenfalls
kann es passieren, daß durch die Funktion andere Daten oder Code überschrieben
werden.

Parameter
char *strncpy(char *ziel, const char *quelle, size_t anzahl);
wchar_t *wcsncpy(wchar_t *ziel, const wchar_t *quelle, size_t anzahl);
● Rückgabewert. Zeiger auf ziel.

Verwandte Funktionen
strcat(), strncat(), strspn()

strpbrk, wcspbrk <string.h><wchar.h>


Zeichen in String suchen

Beschreibung
Die Funktion überprüft die Zeichenkette zkette1 daraufhin, ob in ihr ein beliebiges Zeichen aus
der Zeichenkette zkette2 vorkommt.

Parameter
C:
char *strpbrk(const char *zkette1, const char *zkette2);
wchar_t *wcspbrk(const wchar_t *zkette1, const wchar_t *zkette2);
C++:
const char *strpbrk(const char *zkette1, const char *zkette2);
const wchar_t *wcspbrk(const wchar_t *zkette1, const wchar_t *zkette2);
char *strpbrk(char *zkette1, const char *zkette2);
wchar_t *wcspbrk(wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Die Funktion gibt einen Zeiger zum ersten entsprechenden
Zeichen in zkette1 oder einen NULL-Zeiger zurück, wenn kein identisches
Zeichen gefunden wird.

Verwandte Funktionen
strchr(), strrchr(), strstr()

317
Die C-Standardbibliothek

strrchr, wcsrchr <string.h>


Suche: letztes Vorkommen von Zeichen

Beschreibung
Die Funktion tastet die übergebene Zeichenkette daraufhin ab, ob in ihr ein bestimmtes Zeichen
vorkommt. Das abschließende Nullterminierungszeichen ist in die Suche eingeschlossen und
kann ebenfalls das Zeichen sein, nach dem gesucht wird.

Parameter
C:
char *strrchr(const char *zkette, int zeichen);
wchar_t *wcsrchr(const wchar_t *zkette, wchar_t zeichen);
C++:
const char *strrchr(const char *zkette, int zeichen);
const wchar_T *wcsrchr(const wchar_t *zkette, wchar_t zeichen);
char *strrchr(char *zkette, int zeichen);
wchar_t *wcsrchr(wchar_t *zkette, wchar_t zeichen);
● Rückgabewert. Die Funktion gibt einen Zeiger zum letzten (d. h. am weitesten
rechts liegenden) Vorkommen von zeichen in zkette zurück, wenn das Zeichen
gefunden wurde. Anderenfalls wird ein NULL-Zeiger zurückgegeben.

Verwandte Funktionen
strcspn(), strpbrk(), strspn()

strspn, wcsspn <string.h><wchar.h>


Erstes fremdes Zeichen suchen

Beschreibung
Die Funktion untersucht, bis zu welcher Position zkette1 ausschließlich aus Zeichen besteht,
die in zkette2 enthalten sind.

Parameter
size_t strspn(const char *zkette1, const char *zkette2);
size_t wcsspn(const wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Länge des Präfix bis zum ersten ungleichen Zeichen.

Verwandte Funktionen
strcspn(), strpbrk(), strrchr()

strstr, wcsstr <string.h><wchar.h>


Zeichenkette in anderer finden

318
wctype.h

Beschreibung
Die Funktion sucht nach zkette2 in zkette1.

Parameter
C:
char *strstr(const char *zkette1,const char *zkette2);
wchar_t *strstr(const wchar_t *zkette1, const wchar_t *zkette2);
C++:
const char *strstr(const char *zkette1, const char *zkette2);
const wchar_t *wcsstr(const wchar_t *zkette1, const wchar_t *zkette2);
char *strstr(const char *zkette1, const char *zkette2);
wchar_t *wcsstr(const wchar_t *zkette1, const wchar_t *zkette2);
● Rückgabewert. Zeiger zum ersten Vorkommen von zkette2 in zkette1 zurück,
bzw. einen NULL-Zeiger, wenn zkette2 nicht gefunden wurde.

Verwandte Funktionen
memchr(), strchr(), strcspn(), strrchr()

strtod, wcstod <stdlib.h><wchar.h>


Umwandlung: String in double

Beschreibung
Die Funktion wandelt einen String zkette in eine Gleitkommazahl doppelter Genauigkeit (Typ
double) um. Die Umwandlung wird beendet, nachdem das erste Zeichen, das nicht mehr als
Bestandteil der Zahl erkannt wird, oder **endzgr erreicht wurde.

Parameter
double strtod(const char *zkette, char **endzgr);
double wcstod(const wchar_t *zkette, wchar_t **endzgr);
● Rückgabewert. Die Funktion gibt den umgewandelten Wert zurück.

Verwandte Funktionen
strtol(), strtoul()

strtok, wcstok <string.h><wchar.h>


Suche nächstes Grundsymbol in String

Beschreibung
Die Funktion ermittelt einzelne Grundsymbole in einer Zeichenkette. Um die Grundsymbole zu
finden, sucht sie nach den in zkette2 enthaltenen Trennzeichen.

319
Die C-Standardbibliothek

Ab dem zweiten Aufruf kann für zkette1 das Argument NULL übergeben werden.
Die Funktion sucht dann nach dem nächsten Grundsymbol ab der Stelle, die beim
ersten Aufruf intern gespeichert wurde.
Durch wiederholte Aufrufe der Funktion kann die Zeichenkette zkette1 in eine
Reihe Teil-Strings aufgesplittet werden, die jeweils durch Zeichen aus zkette2 abge-
schlossen werden.
Die Wide Character-Version benötigt einen zusätzlichen Zeiger auf wchar_t, um
Hilfsinformationen ablegen zu können.
char *strtok(char *zkette1, const char *zkette2);
wchar_t *wcstok(wchar_t *zkette1, const wchar_t *zkette2,
wchar_t ** zeiger);
● Rückgabewert. Zeiger auf das gefundene Grundsymbol oder NULL-Zeiger,
wenn keine Token mehr vorhanden sind.

Verwandte Funktionen
strpbrk(), strcspn(), strspn(), strstr()

strtol, wcstol <stdlib.h><wchar.h>


Umwandlung: String in long

Beschreibung
Die Funktion wandelt eine Zeichenkette in einen Wert vom Typ long um. Die Umwandlung wird
beendet, nachdem das erste Zeichen, das nicht mehr als Bestandteil der Zahl erkannt wird, oder
**endzgr erreicht wurde.

Parameter
long strtol(const char *zkette, char **endzgr, int basis);
long int wcstol(const wchar_t *zkette, wchar_t **endzgr, int basis);
● Rückgabewert. Gibt den umgewandelten Wert zurück.

Verwandte Funktionen
strtod(), strtoul(), sprintf(), atof()

strtoul, wcstoul <stdlib.h><wchar.h>


Umwandlung: String in unsigned long

Beschreibung
Die Funktion wandelt eine Zeichenkette in einen Wert vom Typ unsigned long um. Die
Umwandlung wird beendet, nachdem das erste Zeichen, das nicht mehr als Bestandteil der Zahl
erkannt werden konnte, oder **endzgr erreicht wurde.

320
wctype.h

Parameter
unsigned long int strtoul (const char *zkette, char **endzgr, int basis);
unsigned long int wcstoul (const wchar_t *zk,wchar_t **endzgr,int basis);
● Rückgabewert. Bei Erfolg der umgewandelten Wert, anderenfalls Null.

Verwandte Funktionen
strtod(), strtol()

strxfrm, wcsxfrm <string.h><wchar.h>


Umwandlung nach lokaler Einstellung

Beschreibung
Die Funktion wandelt maximal anz Zeichen der Zeichenkette quelle um und schreibt das
Ergebnis nach ziel. Bei erfolgreicher Transformation liefern die Aufrufe:
strcmp(ziel, x)
und
strcoll(quelle, x)
danach das gleiche Ergebnis.

Parameter
size_t strxfrm (char *ziel, char *quelle, size_t anz);
size_t wcsxfrm (wchar_T *ziel, wchar_t *quelle, size_t anz);
● Rückgabewert. Anzahl der transformierten Zeichen.

Verwandte Funktionen
strcmp(), strcoll()

system <stdlib.h>
Betriebssystem-Befehl ausführen

Beschreibung
Mit der Funktion system() kann von einem C-Programm aus ein anderes Programm ausgeführt
werden. Der momentan laufende Prozeß wird unterbrochen, und der übergebene Systembefehl
an den Befehlsinterpreter, falls vorhanden, weitergeleitet.

Parameter
int system(const char *prgname);
● Rückgabewert. Implementierungsspezifisch.

321
Die C-Standardbibliothek

tan, tanh <math.h>


Tangente berechnen

Beschreibung
Die Funktion tan() berechnet den Tangens und tanh() den Tangens hyperbolicus ihres Argu-
ments.

Parameter
double tan(double x);
double tanh(double x);
● Rückgabewert. tan() liefert den Tangens des Arguments im Bereich [ -8, 8 ].
tanh() liefert den Tangens hyperbolicus des Arguments im Bereich [-1, 1].

Warnung
Der Tangens nähert sich in der Umgebung der Vielfachen von p /2 den Werten -8
und 8.

Verwandte Funktionen
acos(), asin(), atan(), atan2(), sinh()
Siehe Beispiel zu Header-Datei math.h

time <time.h>
System-Uhrzeit holen

Beschreibung
Die Funktion time() ermittelt die aktuelle Kalenderzeit. Die Kalenderzeit ist die Anzahl der
Sekunden, die seit dem 1. Januar 1970, [Link] Uhr, vergangen sind.
Wenn das Argument p_zeit kein NULL-Zeiger ist, wird die Kalenderzeit auch an
die Adresse geschrieben, auf die p_zeit zeigt.

Parameter
time_t time(time_t *p_zeit);
● Rückgabewert. Anzahl der seit dem 1.1.1970, [Link] Uhr, verstrichenen
Sekunden.

Verwandte Funktionen
asctime(), ctime(), gmtime(), localtime()
Siehe Beispiel zu Header-Datei time.h

tmpfile <stdio.h>
Vorübergehende Datei anlegen

322
wctype.h

Beschreibung
Die Funktion tmpfile() erzeugt eine temporäre Datei. Die Datei wird im Modus wb+ geöffnet
und automatisch entfernt, wenn die Datei geschlossen wird oder das Programm endet.

Parameter
FILE *tmpfile(void);
● Rückgabewert. Zeiger auf eine FILE-Struktur. Konnte die Datei nicht geöffnet
werden, wird ein NULL-Zeiger zurückgegeben.

Verwandte Funktionen
tmpnam()

tmpnam <stdio.h>
Vorübergehenden Dateinamen schaffen

Beschreibung
Die Funktion tmpnam() erzeugt einen eindeutigen Namen für eine temporäre Datei. Erhält die
Funktion als Argument einen NULL-Zeiger, wird der Name in einen internen statischen Puffer
geschrieben, der von weiteren Aufrufen der Funktion überschrieben wird.
Ansonsten zeigt zkette auf einen Speicherbereich, in dem der Name abgelegt wer-
den soll. Der für den Dateinamen vorgesehene Speicherbereich muß mindestens
L_tmpnam Bytes groß sein. Sie sollten also diese Konstante bei der Definition eines
Arrays auf char als Größenangabe verwenden.

Parameter
char *tmpnam(char *zkette);
● Rückgabewert. Zeiger auf den temporären Namen.

Verwandte Funktionen
tmpfile()

tolower, towlower <ctype.h><wctype.h>


Umwandlung: Groß- in Kleinbuchstaben

Beschreibung
Die Funktion wandelt das übergebene Zeichen in einen Kleinbuchstaben um. Die Funktion
tolower() überprüft, ob der übergebene Buchstabe ein Großbuchstabe ist, zu dem ein Klein-
buchstabe existiert, und nimmt nur dann die Umwandlung vor.

323
Die C-Standardbibliothek

Parameter
int tolower(int zeichen);
wint_t towlower(wchar_t zeichen);
● Rückgabewert. Die Funktion gibt das umgewandelte Zeichen zurück. Wird ein
Kleinbuchstabe übergeben, wird dieser unverändert zurückgeliefert.

Verwandte Funktionen
toupper(), towupper()

toupper, towupper <ctype.h><wctype.h>


Umwandlung: Klein- in Großbuchstaben

Beschreibung
Die Funktion wandelt das übergebene Zeichen in einen Großbuchstaben um. Die Funktion
toupper() überprüft, ob der übergebene Buchstabe ein Großbuchstabe ist, zu dem ein Klein-
buchstabe existiert, und nimmt nur dann die Umwandlung vor.

Parameter
int toupper(int zeichen);
wint_t towupper(wchar_t zeichen);
● Rückgabewert. Die Funktion gibt das umgewandelte Zeichen zurück. Wird ein
Großbuchstabe übergeben, wird dieser unverändert zurückgeliefert.

Verwandte Funktionen
tolower(), towlower()

towctrans <wctype.h>
Wide Character-Abbildung

Beschreibung
Konvertiert ein Wide Character-Zeichen gemäß der durch die Parameterbeschreibung gegebe-
nen Abbildung. Argumente für die Parameterbeschreibung können mit Hilfe der Funktion
wctrans() erzeugt werden.

Parameter
wint_t towctrans(wint_t wc, wctrans_t beschreibung);
● Rückgabewert. Wert, auf den das Zeichen abgebildet wurde.

Verwandte Funktionen
wctrans()

324
wctype.h

ungetc, ungetwc <stdio.h><wchar.h>


Zeichen zurück an Stream schicken

Beschreibung
Die Funktion schreibt das eingelesene Zeichen zurück an den Stream. Die Funktion kann nicht
beliebig viele Male hintereinander ausgeführt werden. Bei gepufferter Ein- und Ausgabe wird
das Zeichen in den Puffer geschrieben und geht entsprechend bei Operationen, die den Puffer
löschen (fseek(), rewind(), fflush(), fsetpos()), verloren.

Parameter
int ungetc(int zeichen, FILE *stream);
wint_t ungetwc(wchar_t zeichen, FILE *stream);
● Rückgabewert. Die Funktion gibt das Argument zeichen zurück, wenn erfolg-
reich, sonst EOF (WEOF).

Verwandte Funktionen
getc(), getchar()

va_... <stdarg.h>
Variable Anzahl von Argumenten

Beschreibung
Die Makros va_arg(), va_end() und va_start() dienen zur Implementierung von Funktionen,
die mit einer variablen Anzahl von Argumenten aufgerufen werden, wie beispielsweise
printf() oder scanf().

Parameter
type va_arg(va_list arg_zgr, type);
void va_end(va_list arg_zgr);
void va_start(va_list arg_zgr, letzter_param);

Verwandte Funktionen
vfprintf(), vprintf(), vsprintf()

v-,vf-,vs- (w)printf <stdio.h><wchar.h>


Formatierte Daten ausgeben

Beschreibung
Diese sechs Funktionen geben formatierte Daten aus. Sie sind mit den Funktionen fprintf(),
printf() und sprintf() nahezu identisch. Die variable Anzahl von Argumenten wird nicht als
Liste, sondern als Zeiger auf eine Liste von Argumenten übergeben.

325
Die C-Standardbibliothek

Die drei Funktionen unterscheiden sich durch das Ziel ihrer Ausgabe. vfprintf()
schreibt an einen beliebigen Stream, vprintf() an den Stream stdout und vsprintf()
in einen Speicherbereich.

Parameter
int vfprintf(FILE *stream, const char *format, va_list argzgr);
int vfwprintf(FILE *stream, const wchar_t *format, va_list argzgr);
int vprintf(const char *format, va_list argzgr);
int vwprintf(const wchar_t *format, va_list argzgr);
int vsprintf(char *puffer, const char *format, va_list argzgr);
int vswprintf(wchar_t *puffer, size_t n, const wchar_t *format,
va_list argzgr);
● Rückgabewert. Die drei Funktionen geben die Anzahl der geschriebenen Zei-
chen ohne das »\0«-Zeichen zurück. Im Fehlerfall wird ein negativer Wert zu-
rückgeliefert.

Verwandte Funktionen
fprintf(), printf(), sprintf(), va_arg(), va_end(), va_start()

wcstombs, wcsrtombs <stdlib.h><wchar.h>


wchar_t zu Multibyte

Beschreibung
Beide Funktionen konvertieren die übergebene Folge von wchar_t-Zeichen in einen Multibyte-
String. Die Konvertierung bricht ab, wenn n Bytes konvertiert wurden oder ein Nullterminie-
rungszeichen oder ein ungültiges Multibyte-Zeichen aufgetreten ist. Werden genau n Bytes
ohne abschließendes Nullterminierungszeichen konvertiert, ist der String nicht nullterminiert.
Die Konvertierung berücksichtigt die lokale Einstellung der Kategorie LC_TYPE.
Die Funktion wcstomb() erzeugt eine Folge von Multibyte-Zeichen im anfänglichen
Shift-Status (Zustand in dem die Zeichen aus dem C-Zeichensatz 1:1 codiert sind).
Die Funktion wcsrtomb() erzeugt eine Folge von Multibyte-Zeichen im durch den
mbstate_t-Argument gegebenen Konvertierungsstatus.

Parameter
size_t wcstombs(char *mb_str, const wchar_t *wc, size_t n);
size_t wcsrtombs(char *mb_str,const wchar_t *wc,size_t n,mbstate_t *ps);
● Rückgabewert. Anzahl der geänderten Bytes (ohne Nullterminierungszei-
chen), bzw. -1 im Fehlerfall.

Verwandte Funktionen
wctomb(), wcrtomb()

326
wctype.h

wctob <wchar.h>
1-Byte-Repräsentation abfragen

Beschreibung
Bestimmt, ob es sich bei dem Zeichen c um ein Zeichen eines erweiterten Zeichensatzes han-
delt, dessen Multibyte-Darstellung im anfänglichen Shift-Status (Zustand in dem die Zeichen
aus dem C-Zeichensatz 1:1 codiert sind) ein einzelnes Byte ist.

Parameter
int wctob(wint_t c);
● Rückgabewert. 1-Byte-Repräsentation des übergebenen Zeichens. EOF, wenn
das Zeichen nicht mit einem MultiByte-Zeichen korrespondiert, das im an-
fänglichen Konvertierungsstatus nur aus einem Byte besteht.

Verwandte Funktionen
btowc()

wctomb, wcrtomb <stdlib.h><wchar.h>


wchar_t zu Multi-Byte

Beschreibung
Beide Funktionen konvertieren das übergebene wchar_t-Zeichen in ein Multibyte-Zeichen. Die
Konvertierung bricht nach spätestens MB_CUR_MAX Zeichen ab. Die Konvertierung berücksichtigt
die lokale Einstellung der Kategorie LC_TYPE.

Parameter
int wctomb(char *mb_ch, const wchar_t *wc);
size_t wcrtomb(char *mb_ch, const wchar_t *wc, mbstate_t *ps);
● Rückgabewert. Anzahl der geänderten Bytes (ohne Nullterminierungszei-
chen), bzw. -1 im Fehlerfall.

Verwandte Funktionen
wcstombs()

wctrans <wctype.h>
Wide Character-Abbildung kennzeichnen

Beschreibung
Erzeugt einen Wert des Typ wctrans_t, der die durch den Parameter eigenschaft beschriebene
Abbildung von einem Wide Character-Zeichensatz in einen anderen (nach LC_TYPE) identifi-
ziert. Wird zusammen mit towctrans() benutzt.

327
Die C-Standardbibliothek

Parameter
wctrans_t wctrans(const char *eigenschaft);
● Rückgabewert. Wert, der eine gemäß LC_TYPE gültige Wide Character-Abbil-
dung repräsentiert und als zweites Argument an towctrans() übergeben werden
kann.

Verwandte Funktionen
towctrans()

wctype <wctype.h>
Wide Character-Klasse kennzeichnen

Beschreibung
Erzeugt einen wctype_t-Wert, der die Klasse von Wide Characters bezeichnet, die als Argument
übergeben wurde. Wird zusammen mit iswctype() verwendet und erlaubt die Identifizierung
einer Klasse anhand eines Strings.

Parameter
wctype_t wctype(const char *eigenschaft);
● Rückgabewert. Wert, der eine Wide Character-Klasse repräsentiert und als
zweites Argument an iswctype() übergeben werden kann.

Verwandte Funktionen
iswctype()

328
Die C++-Standardbibliothek

Übersicht über die Standardbibliothek


Die in der C++-Standardbibliothek definierten Klassen und Funktionen können in
verschiedene Gruppen aufgeteilt werden:
● Die Container-Klassen implementieren die gängigsten Modelle zur Behandlung
und Speicherung von Daten. Die verschiedenen Modelle erlauben es, Datenob-
jekte nach bestimmten Kriterien abzulegen, beispielsweise als einfache Menge
(set) oder als Keller (stack).
● Iteratoren dienen dazu, auf bequeme und einheitliche Weise auf die Elemente
in Containern zugreifen zu können.
● Algorithmen. In der Header-Datei <algorithm> sind eine Reihe von praktischen
Funktionen implementiert, die mit Hilfe von Iteratoren die Elemente in Con-
tainern manipulieren.
● Die Stream-Klassen bilden eine kleine Klassenhierarchie zur Regelung des ge-
pufferten oder ungepufferten Datenflusses zwischen Festspeicher, Arbeitsspei-
cher und Bildschirm.
● Die String-Klassen bieten eine komfortablere und weniger fehleranfällige Al-
ternative zum Umgang mit Zeichenketten.
● Die Klasse locale und die zugehörigen Facettenklassen dienen zur Anpassung
an lokale Besonderheiten.
● Die mathematischen Klassen umfassen vor allem die beiden Klassen valarray
(besonders für die Verwendung auf Parallelrechnern ausgelegt) und complex
(zur Behandlung komplexer Zahlen).
● Die Diagnoseklassen ermöglichen Typidentifikationen zur Laufzeit (wichtig
bei Zeigern auf Klasseninstanzen) und objektorientierte Fehlerbehandlung.
● Die restlichen Utility-Klassen unterstützen beispielsweise die dynamische Spei-
cherallokation und die Programmierung mit Funktionsobjekten.

329
Die C++-Standardbibliothek

Die Header-Dateien
Ebenso wie in C viele wichtige und häufig gebräuchliche Funktionen fester
Bestandteil der C-Laufzeitbibliothek sind, umfaßt C++ standardmäßig eine Reihe
nützlicher Klassen und Klassenhierarchien. Diese Klassen sind ebenfalls Teil der
Laufzeitbibliothek. Um auf diese Klassen zugreifen zu können, müssen wiederum
die entsprechenden Header-Dateien mittels #include-Anweisungen eingebunden
werden.
Die C++-Klassen erweitern zum einen die Laufzeitbibliothek um neue Funktionali-
täten und Einsatzbereiche, zum anderen werden bestehende Konzepte objektorien-
tiert implementiert. Dies gilt insbesondere für die Stream-Klassen, die zur Regelung
des Datenflusses zwischen Arbeitsspeicher, Bildschirm und Festplatte dienen und
damit die Funktionen aus der Header-Datei stdio.h ersetzen.
Dies bedeutet aber nicht, daß die alten C-Funktionen nicht mehr verfügbar wären
oder man nicht beide Systeme mischen könnte. Ob Sie sich der C++-Klassen oder
der C-Funktionen bedienen, oder beide Konzepte nebeneinander in einem Pro-
gramm verwenden, ist gänzlich Ihnen überlassen. Alles andere würde auch der
Kompatibilität von C und C++ widersprechen. Teilweise wird die Mischung sogar
absichtlich unterstützt, indem Standard C-Funktionen überladen werden, um
zusammen mit den Klassen der Laufzeitbibliothek verwendet werden zu können.
Die Elemente der C++-Laufzeitbibliothek sind in dem Namensbereich std einge-
schlossen. Üblicherweise läßt man daher auf die #include-Anweisungen für die Hea-
der-Dateien die Anweisung
using namespace std;
folgen.

Warnung
Noch werden aber nicht alle Elemente der C++Bibliothek von allen Compilern
unterstützt. Manche Compiler unterstützen keine Namensbereiche oder haben
nicht alle Klassen der Laufzeitbibliothek im Namensbereich std deklariert. Manche
Compiler bieten Teile der Laufzeitbibliothek in den alten C-Headern an, beispiels-
weise iostream.h statt iostream.

algorithm
Beschreibung
Enthält eine ganze Reihe von Funktionentemplates, die die gängigsten Algorithmen zur
Anwendung auf Container-Elementen implementieren (Kopieren, Verschieben, Sortieren,

330
algorithm

Suchen, etc.). Unter Containern sind hier allerdings nicht nur die in der C++-Laufzeitbibliothek
definierten Container zu verstehen. Algorithmen können in gleicher Weise auch auf selbst defi-
nierte Container oder auch simple Arrays angwendet werden – Voraussetzung ist lediglich, daß
für den Zugriff auf die Elemente im Container passende Iteratoren zur Verfügung stehen und
die Elemente geeignet sind, von den Algorithmen bearbeitet zu werden.

Enthaltene Funktionentemplates
adjacent_find() // Benachbarte Vorkommen aufspüren
binary_search() // Element in sortierter Sequenz suchen
copy() // Sequenz kopieren (beginnt mit erstem Element)
copy_backward() // Sequenz kopieren (beginnt mit letztem Element)
count() // Elemente in Sequenz zählen
count_if() // Bestimmte Elemente in Sequenz zählen
equal() // Elemente in Sequenz paarweise vergleichen
equal_range() // Einheitliche Sequenz suchen
fill() // Elemente in Sequenz einen Wert zuweisen
fill_n() // Den ersten n Elementen in Sequenz
// einen Wert zuweisen
find() // Wert in Sequenz suchen
find_end() // Letztes Vorkommen einer Teilsequenz suchen
find_first_of() // Element in Sequenz suchen
find_if() // Bestimmtes Element suchen
for_each() // Funktion auf Elemente anwenden
generate() // Sequenz einen berechneten Wert zuweisen
generate_n() // Ersten Elementen einer Sequenz einen
// berechneten Wert zuweisen
includes() // Sequenz enthalten in anderer Sequenz
inplace_merge() // Zwei Sequenzen vermengen
iter_swap() // Zwei Elemente tauschen
lexicographical_compare() // zwei Sequenz lexikographisch vergleichen
lower_bound() // Element in sortierte Sequenz einfügen
make_heap() // Sequenz in Heap umwandeln
max() // Maximum zweier Werte bestimmen
max_element() // Maximum einer Sequenz bestimmen
merge() // Zwei Sequenzen vermengen
min() // Minimum zweier Werte bestimmen
min_element() // Minimum einer Sequenz bestimmen
mismatch() // Ersten Elemente zweier Sequenzen, die
// nicht gleich sind, aufspüren
next_permutation() // Nächste Permutation erzeugen
nth_element() // ntes Element einsortieren
partial_sort() // Teilsequenz sortieren
partial_sort_copy() // Teilsequenz sortiert kopieren
partition() // Ausgewählte Elemente nach vorne kopieren
pop_heap() // Element von Heap entfernen
prev_permutation() // Vorangehende Permutation erzeugen
push_heap() // Element in Heap einfügen
random_shuffle() // Elemente in Sequenz neu verteilen
remove() // Elemente mit bestimmtem Wert entfernen

331
Die C++-Standardbibliothek

remove_copy() // Nur Elemente kopieren, die ungleich


// einem bestimmten Wert sind
remove_copy_if() // Ausgewählte Elemente kopieren
remove_if() // Bestimmte Elemente entfernen
replace() // Elemente mit bestimmtem Wert ersetzen
replace_copy() // Sequenz kopieren, bestimmte kopierte
// Elemente durch Wert ersetzen
replace_copy_if() // Sequenz kopieren, bestimmte kopierte
// Elemente durch Wert ersetzen
replace_if() // Bestimmte Elemente ersetzen
reverse() // Reihenfolge der Elemente umkehren
reverse_copy() // Sequenz in umgekehrter Reihenfolge kopieren
rotate() // Elemente rotieren
rotate_copy() // Sequenz in rotierter Reihenfolge kopieren
search() // Teilsequenz suchen
search_n() // Teilsequenz mit identischen Werten suchen
set_difference() // Differenz zweier sortierter Sequenzen
// (für Elemente aus A, aber nicht B)
set_intersection() // Schnitt zweier sortierter Sequenzen
set_symmetric_difference() // Differenz zweier sortierter Sequenzen
// (für Elemente entweder in A oder B)
set_union() // Vereinigung zweier sortierter Sequenzen
sort() // Sequenz sortieren
sort_heap() // Heap sortieren
stable_partition() // Ausgewählte Elemente unter Beibehaltung
// ihrer relativen Ordnung nach vorne kopieren
stable_sort() // Sequenz sortieren (Reihenfolge gleicher
// Elemente bleibt erhalten)
swap() // Zwei Elemente tauschen
swap_ranges() // Elemente zweier Sequenzen tauschen
transform() // Elementen einer Sequenz neue Werte zuweisen
unique() // Duplikate aus Sequenz entfernen
unique_copy() // Sequenz ohne Duplikate kopieren
upper_bound() // Element in sortierte Sequenz einfügen

bitset
Beschreibung
Definiert ein Klassentemplate und einige überladene Operatoren zur Verwaltung und Bearbei-
tung von Bitfolgen feststehender Größe.

Enthaltene Klassentemplates
bitset // Für Bit-Folgen feststehender Größe

Überladene Operatoren
&, |, ^, <<, >>

332
complex

Beispiel
#include <iostream>
#include <bitset>
using namespace std;

int main(int argc, char **argv)


{
enum optionen {op1, op2, op3, op4};

bitset<4> options("0100"); // Bits initialisieren

[Link](op1); // Letztes Bit setzen


[Link](op3,0); // 3. Bit von rechts auf Null setzen

cout << "Optionen: " << options << endl;


for(int loop = op1; loop <= op4; loop++)
if(options[loop])
cout << loop << "-te Option gesetzt" << endl;
else
cout << loop << "-te Option nicht gesetzt" << endl;
return 0;
}

complex
Beschreibung
Definiert das Klassentemplate complex einschließlich Spezialisierungen des Klassentemplates
für die Datentypen float, double und long double, für die Programmierung mit komplexen
Zahlen. Zudem sind etliche Funktionentemplates und überladene Operatoren für die Verwen-
dung mit complex-Objekten definiert.

Enthaltene Klassentemplates
complex // Klasse für komplexe Zahlen.
complex<double> // Spezialisierung für Datentyp double.
complex<float> // Spezialisierung für Datentyp float.
complex<long double> // Spezialisierung für Datentyp long double.

Enthaltene Funktionentemplates
abs() // Betrag berechnen.
arg() // Argument ermitteln.
conj() // Konjugiert Komplexe bestimmen.
cos() // Kosinus berechnen.
cosh() // Kosinus hyperbolicus berechnen.
exp() // Exponentialfunktion berechnen.
imag() // Imaginärteil bestimmen.

333
Die C++-Standardbibliothek

log() // Natürlichen Logarithmus berechnen.


log10() // Logarithmus zur Basis 10 berechnen.
norm() // Norm bestimmen.
polar() // Komplexe Zahl aus Polarform bestimmen.
pow() // Zahl potenzieren.
real() // Realteil bestimmen.
sin() // Sinus berechnen.
sinh() // Sinus hyperbolicus berechnen.
sqrt() // Quadratwurzel berechnen.
tan() // Tangens berechnen.
tanh() // Tangens hyperbolicus berechnen.

Überladene Operatoren
+, –, *, /, +, –, ==, !=, <<, >>

Beispiel
#include <complex>
using namespace std;

complex<double> zahl(32,6, -5.1);

deque
Beschreibung
Definiert das Klassentemplate deque, das einen Container zur Verwaltung von Objekten beliebi-
ger Datentypen implementiert. Zusätzlich sind Funktionen (swap()) und Operatoren zur
Anwendung auf deque-Objekte definiert.

Enthaltene Templates
deque // Datenstruktur, die für Einfügen/Löschen am Anfang
// und Ende optimiert ist und schnellen direkten Zugriff
// auf beliebige Positionen zuläßt.
swap() // Zum Vertauschen der Elemente zweier deque-Container.

Überladene Operatoren
==, !=, <, >, >=, <=

Beispiel
#include <deque>
using namespace std;

class demo;

334
exception

deque<int> container(5); // deque-Container für int-Objekte


deque<demo> container(5); // deque-Container für demo-Objekte

exception
Beschreibung
Enthält verschiedene Klassen, Typdefinitionen und Funktionen, die mit der Exception-Behand-
lung in C++-Programmen in Zusammenhang stehen.

Enthaltene Klassen und Typdefinitionen


exception // Basisklasse, der in der Laufzeitbibliothek
// definierten Exception-Klassen.
bad_exception // Für Exception-Objekte, die von
// der Funktion unexpected()
// ausgelöst werden.
typedef void (*terminate_handler)() // Typ des Funktionsarguments zu
// set_terminate()
typedef void (*unexpected_handler)() // Typ des Funktionsarguments zu
// set_unexpected()

Enthaltene Funktionen
terminate() // Ruft Funktion zum Programmabbruch auf.
set_terminate() // Richtet eine Funktion zum Programmabbruch ein.
unexpected() // Ruft Funktion zur Behandlung unerwarteter
// Exceptions auf.
set_unexpected() // Richtet Funktion zur Behandlung unerwarteter
// Exceptions ein.
uncaught_exception() // Liefert true, wenn eine noch nicht abgefangene
// Exception ausgelöst wurde.

Verweise
Siehe Kategorie Sprachkonzepte, Exception-Behandlung

fstream
Beschreibung
Enthält Klassentemplates für Dateistreams und die dazugehörigen Puffer. Für die Zeichentypen
char und wchar_t sind bereits entsprechende Klassen aus den Templates instanziiert, die man
direkt in Programmen verwenden kann.

335
Die C++-Standardbibliothek

Enthaltene Klassentemplates
basic_fstream // Stellt HighLevel-Routinen zur Ein- und Ausgabe von
// und in Dateien zur Verfügung.
basic_ifstream // Stellt HighLevel-Routinen zum Einlesen aus einer
// Datei zur Verfügung.
basic_ofstream // Stellt HighLevel-Routinen zum Ausgeben in eine
// Datei zur Verfügung.
basic_filebuf // Von basic_streambuf abgeleiteter Puffer, der die
// Ein- und Ausgabe mit einer Datei verknüpft.

Enthaltene Klassen
fstream // typedef basic_fstream<char> fstream
wfstream // typedef basic_fstream<wchar_t> wfstream
ifstream // typedef basic_ifstream<char> ifstream
wifstream // typedef basic_ifstream<wchar_t> wifstream
ofstream // typedef basic_ofstream<char> ofstream
wofstream // typedef basic_ofstream<wchar_t> wofstream
filebuf // typedef basic_filebuf<wchar_t> filebuf
wfilebuf // typedef basic_filebuf<wchar_t> wfilebuf

functional
Beschreibung
Funktionsobjekte sind Klasseninstanzen, für die in den vielen Fällen lediglich der ()-Operator
definiert ist. Der Operator erlaubt es, Objekte dieser Klassen wie Funktionsaufrufe einzusetzen,
da die Anwendung des Operators auf eine Instanz der Klasse syntaktisch genauso aussieht wie
ein Funktionsaufruf. In der STL werden Funktionsobjekte häufig als Parameter zu den Algorith-
men eingesetzt.
Zur weiteren Unterstützung der Programmierung mit Funktionsobjekten sind in der Header-
Datei noch etliche Hilfsdatentypen, Klassen und Funktionen definiert.

Enthaltene Funktionsobjekte
divides // Funktionsobjekt zur Division.
equal_to // Funktionsobjekt zum Test auf Gleichheit.
greater // Funktionsobjekt, äquivalent zu >.
greater_equal // Funktionsobjekt, äquivalent zu >=.
less // Funktionsobjekt, äquivalent zu <.
less_equal // Funktionsobjekt, äquivalent zu <=.
logical_and // Funktionsobjekt, äquivalent zu &&.
logical_not // Funktionsobjekt, äquivalent zu !.
logical_or // Funktionsobjekt, äquivalent zu ||.
minus // Funktionsobjekt zur Subtraktion.
modulus // Funktionsobjekt zur Modulo-Berechnung
// (Rest der Division).

336
functional

multiplies // Funktionsobjekt zur Multiplikation.


negate // Funktionsobjekt zur Negation.
not_equal_to // Funktionsobjekt zum Test auf Ungleichheit.
plus // Funktionsobjekt zur Addition.

Enthaltene Hilfselemente
binary_function // Basisklasse für Funktionsobjekte
// mit zwei Argumenten.
binary_negate // Hilfsklasse zur Negation einer Aussage
// mit zwei Argumenten.
bind1st() // Funktion, die das erste Argument eines
// Funktionsobjekts für zwei Argumente mit
// einem konstanten Wert verbindet.
bind2nd() // Funktion, die das zweite Argument eines
// Funktionsobjekts für zwei Argumente mit
// einem konstanten Wert verbindet.
binder1st // Hilfsklasse zur Bindung eines Wertes an das
// erste Argument eines Funktionsobjektes.
binder2nd // Hilfsklasse zur Bindung eines Wertes an das
// zweite Argument eines Funktionsobjektes.
mem_fun_t // Hilfsklasse zur Übergabe von Methoden ohne
// Argument an Funktionsobjekt-Parameter.
mem_fun1_t // Hilfsklasse zur Übergabe von Methoden mit
// einem Argument an Funktionsobjekt-Parameter.
mem_fun() // Hilfsfunktion zur Übergabe von Methoden ohne
// Argument an einen Funktionsobjekt-Parameter
mem_fun1() // Hilfsfunktion zur Übergabe von Methoden mit
// einem Argument an einen Funktionsobjekt-Parameter
mem_fun_ref_t // Hilfsklasse zur Übergabe von Methoden ohne
// Argument an Funktionsobjekt-Parameter
mem_fun1_ref_t // Hilfsklasse zur Übergabe von Methoden mit
// einem Argument an Funktionsobjekt-Parameter.
mem_fun_ref() // Hilfsfunktion zur Übergabe von Methoden ohne
// Argument an einen Funktionsobjekt-Parameter.
mem_fun1_ref() // Hilfsfunktion zur Übergabe von Methoden mit einem
// Argument an einen Funktionsobjekt-Parameter.
not1() // Negiert eine unäre Aussage (Funktionsobjekt
// mit Rückgabetyp bool).
not2() // Negiert eine binäre Aussage (Funktionsobjekt
// mit Rückgabetyp bool).
pointer_to_binary_function // Zur Erzeugung von Funktionsobjekten aus
// Zeigern auf Funktionen mit zwei Argumenten
pointer_to_unary_function // Zur Erzeugung von Funktionsobjekten aus
// Zeigern auf Funktionen mit einem Argument
ptr_fun() // Hilfsfunktion, die es ermöglicht eine Funktion an
// einen Binder oder einen Negator zu übergeben.
unary_function // Basisklasse für Funktionsobjekte mit
// einem Argument
unary_negate // Hilfsklasse zur Negation einer Aussage mit
// einem Argument

337
Die C++-Standardbibliothek

Beispiel
// Verwendung eines Funktionsobjekts
// Werte sortieren;
stable_sort([Link](), [Link](), less<int>());

// Verwendung eines Binders


// ersten Wert groesser 500 suchen
iter i = find_if([Link](), [Link](),
bind2nd(greater<int>(),500));

iomanip
Beschreibung
Enthält Manipulatoren zur Konfiguration von Streams (werden wie Daten an Streams
geschickt).

Enthaltene Funktionen
resetiosflags // Formatierungsflag löschen.
setbase // Basis des Zahlensystems festlegen.
setfill // Füllzeichen festlegen.
setiosflags // Formatierungsflag setzen.
setprecision // Genauigkeit festlegen.
setw // Feldbreite festlegen.

Beispiel
#include <iomanip>
using namespace std;

cout << setw(7);


cout << 1.23;
cout << setw(7);
cout << "Ha!" << endl; // Ausgabe: 1.23 Ha!

Verweise
Siehe Kategorie Ein- und Ausgabe, Streams in C++

ios
Beschreibung
Enthält Typdefinitionen und Basisklassen für die Stream-Klassentemplates sowie eine Reihe
von Manipulatoren zur Konfiguration von Stream-Eingaben und -Ausgaben.

338
ios

Enthaltene Klassen und Typdefinitionen


basic_ios // Basisklasse der Stream-Klassen.
ios_base // Klasse, die Aufzählungstypen, Bitfelder und verwandte
// Funktionen für die Streamkonfiguration und -diagnose
// enthält. Dient als Basisklasse zu basic_ios
fpos // Hilfsklasse für Streamstatus und Dateipositionierung.
streamoff // Hilfstyp für Streams.
streamsize // Integer-Typ, der als Rückgabetyp der Schreib- und
// Lesemethoden verwendet wird (soweit diese die Anzahl
// gelesener oder geschriebener Zeichen zurückliefern).

Enthaltene Manipulatoren
boolalpha // bool-Typ berücksichtigen.
dec // Dezimaldarstellung.
hex // Hexadezimaldarstellung.
fixed // Feste Stellenzahl.
internal // Bestimmte Stellen mit Füllzeichen.
left // Linksbündige Ausgabe.
noboolalpha // bool-Typ nicht berücksichtigen.
noshowbase // Basis des Zahlensystems nicht anzeigen.
noshowpoint // Gleitkommazahlen ohne Dezimalpunkt.
noshowpos // Positive Zahlen ohne Vorzeichen.
noskipws // Whitespace miteinlesen.
nouppercase // Keine Konvertierung in Großbuchstaben.
oct // Oktaldarstellung.
right // Rechstbündige Ausgabe.
scientific // Darstellung mit Mantisse und Exponent.
showbase // Basis des Zahlensystems anzeigen.
showpoint // Gleitkommazahlen mit Dezimalpunkt.
showpos // Positive Zahlen mit Vorzeichen.
skipws // white space nicht einlesen.
uppercase // Bestimmte Zeichen als Großbuchstaben.

Beispiel
[Link](10);
cout << 1234.5 << endl;
[Link](10);
cout << left << 1234.5 << endl;
Ausgabe:
1234.5
1234.5

Verweise
Siehe Kategorie Ein- und Ausgabe, Streams in C++

339
Die C++-Standardbibliothek

iosfwd
Beschreibung
Enthält die folgenden Typdefinitionen (Instanziierungen von Stream-Klassen aus den Templa-
tes der Stream-Bibliothek) und die dafür erforderlichen Vorwärtsdeklarationen der Templates.

Enthaltene Klassendefinitionen
typedef basic_ios<char> ios;
typedef basic_ios<wchar_t> wios;
typedef basic_streambuf<char> streambuf;
typedef basic_istream<char> istream;
typedef basic_ostream<char> ostream;
typedef basic_iostream<char> iostream;
typedef basic_stringbuf<char> stringbuf;
typedef basic_istringstream<char> istringstream;
typedef basic_ostringstream<char> ostringstream;
typedef basic_stringstream<char> stringstream;
typedef basic_filebuf<char> filebuf;
typedef basic_ifstream<char> ifstream;
typedef basic_ofstream<char> ofstream;
typedef basic_fstream<char> fstream;
typedef basic_streambuf<wchar_t> wstreambuf;
typedef basic_istream<wchar_t> wistream;
typedef basic_ostream<wchar_t> wostream;
typedef basic_iostream<wchar_t> wiostream;
typedef basic_stringbuf<wchar_t> wstringbuf;
typedef basic_istringstream<wchar_t> wistringstream;
typedef basic_ostringstream<wchar_t> wostringstream;
typedef basic_stringstream<wchar_t> wstringstream;
typedef basic_filebuf<wchar_t> wfilebuf;
typedef basic_ifstream<wchar_t> wifstream;
typedef basic_ofstream<wchar_t> wofstream;
typedef basic_fstream<wchar_t> wfstream;
typedef fpos<char_traits<char>::state_type> streampos;
typedef fpos<char_traits<wchar_t>::state_type> wstreampos;

iostream
Beschreibung
Definiert eine Reihe von Stream-Objekten, die bei Start jedes Programmes automatisch einge-
richtet werden und zur Verfügung stehen.

Definitierte Standard-Stream-Objekte
istream cin // StandardEingabe-Stream für char
ostream cout // StandardAusgabe-Stream für char

340
istream

ostream cerr // Standardfehlerausgabe für char


ostream clog // Standardprotokollausgabe für char
wistream wcin // StandardEingabe-Stream für wchar_t
wostream wcout; // StandardAusgabe-Stream für wchar_t
wostream wcerr // Standardfehlerausgabe für wchar_t
wostream wclog // Standardprotokollausgabe für wchar_t

Beispiel
#include <string>
#include <iostream>
int main(int argc, char **argv)
{
string str;
int wert;
cout << "Geben Sie einen String und einen int-Wert ein" << endl;
cin >> str >> wert;
cout << left; // Manipulator
cout << setw(10) << "String =" << setw(10) << str << endl;
cout << setw(10) << "Wert =" << setw(10) << wert << endl;
return 0;
}

Verweise
Siehe Kategorie Ein- und Ausgabe, Streams in C++

istream
Beschreibung
Enthält das Klassentemplate basic_istream zur Unterstützung von Leseoperationen auf Stre-
ams, sowie zwei Instanziierungen des Templates für die Datentypen char und wchar_t, die man
in Programmen direkt verwenden kann.

Enthaltene Templates
basic_istream // Stellt HighLevel-Routinen zum Einlesen aus
// einem Stream zur Verfügung.
basic_iostream // Stream zu Lesen und Schreiben
// einem Stream zur Verfügung.
ws // Manipulator zum Überlesen von Whitespace

Enthaltene Klassen
istream // Spezialisierung für Datentyp char
wistream // Spezialisierung für Datentyp wchar_t

341
Die C++-Standardbibliothek

Beispiel
filebuf datei;
[Link]("[Link]", ios_base::in | ios_base::out);
istream dat_ein(&datei);
ostream dat_aus(&datei);

iterator
Beschreibung
Iteratoren dienen dazu, Elemente von Containern zu dereferenzieren. Ihr Einsatz ähnelt der
Indizierung von Arrays. Die meisten der Funktionen aus <algorithm> arbeiten mit Iteratoren. In
der Header-Datei sind einige Iteratoren (in Form von Templates) vordefiniert. Des weiteren
enthält die Datei verschiedene Strukturen für die Definition eigener Iteratoren und Hilfsfunk-
tionen für die Programmierung mit Iteratoren.

Hilfsfunktionen
advance() // Iterator verrücken
distance() // Distanz zwischen zwei Iteratoren ermitteln
back_inserter() // Liefert einen Back-Inserter für einen Container
front_inserter() // Liefert einen Front-Inserter für einen Container
inserter() // Liefert einen Inserter für einen Container

Iteratoren-Templates
back_insert_iterator // Iterator zum Einfügen am Ende einer
// Datenstruktur.
front_insert_iterator // Iterator zum Einfügen am Anfang einer
// Datenstruktur.
insert_iterator // Iterator zum Einfügen an beliebiger Stelle in
// eine Datenstruktur.
istream_iterator // Iterator zum Lesen aus einen Stream.
istreambuf_iterator // Iterator zum Lesen aus einen Streampuffer.
ostream_iterator // Iterator zum Schreiben in einen Stream.
ostreambuf_iterator // Iterator zum Schreiben in einen Streampuffer.
reverse_iterator // Random Access-Iterator, der die Datenstruktur
// in umgekehrter Richtung durchläuft.

Hilfsstrukturen
bidirectional_iterator_tag // Vordefinierte Struktur als Hilfe zur
// Erstellung eigener Iteratoren.
forward_iterator_tag // Vordefinierte Struktur als Hilfe zur
// Erstellung eigener Iteratoren.
input_iterator_tag // Vordefinierte Struktur als Hilfe zur
// Erstellung eigener Iteratoren.
iterator // Basisklasse zur Definition von Iteratoren

342
limits

iterator_traits // Struktur mit Charakteristika


// von Iteratoren
output_iterator_tag // Vordefinierte Struktur als Hilfe zur
// Erstellung eigener Iteratoren.
random_access_iterator_tag // Vordefinierte Struktur als Hilfe zur
// Erstellung eigener Iteratoren

Überladene Operatoren
Für reverse_iterator: // ==, <, !=, >, >=, <=, –, +
Für istream_iterator: // ==, !=
Für istreambuf_iterator: // ==, !=

Beispiel
deque<int> container(5);
typedef deque<int>::iterator iter;
...
for(iter i = [Link](); i != [Link](); i++) {
cout << *i << endl;
}

limits
Beschreibung
Enthält das Klassentemplate numeric_limits und seine Spezialisierungen für die verschiede-
nen Datentypen, die der Programmierer zum Abfragen implementierungsspezifischer Charakte-
ristika der elementaren Datentypen nutzen kann.

Enthaltene Elemente
float_round_style // Aufzählungstyp mit folgenden Werten:
// round_indeterminate (-1)
// round_toward_zero (0)
// round_to_nearest (1)
// round_toward_infinity(2)
// round_toward_neg_infinity(3)
numeric_limits // Template-Klasse mit Informationen zur
// implementierungsspezifischen Darstellung
// der numerischen Datentypen.
// Mit Spezialisierungen für:
// bool
// char, signed char, unsigned char, wchar_t
// short, int, long
// unsigned short, unsigned int, unsigned long
// float, double, long double

343
Die C++-Standardbibliothek

Beispiel
#include <limits>
using namespace std;
...
cout << "Int: " << setw(14) << numeric_limits<int>::min()
<< setw(14) << numeric_limits<int>::max() << endl;

list
Beschreibung
Definiert das Klassentemplate list, das einen Container zur Verwaltung von Objekten beliebi-
ger Datentypen implementiert. Zusätzlich sind Funktionen (swap()) und Operatoren zur
Anwendung auf list-Objekte definiert.

Die enthaltenen Funktionen und Klassen


list // Datenstruktur, mit schnellem Einfügen/Löschen
// auf allen Positionen, kein direkter Zugriff
swap() // Zum Vertauschen der Elemente zweier list-Container.

Überladene Operatoren
==, !=, <, >, >=, <=

Beispiel
#include <list>
using namespace std;

class demo;
list<int> container(5); // list-Container für int-Objekte
list<demo> container(5); // list-Container für demo-Objekte

locale
Beschreibung
In bestimmten Anwendungen ist es notwendig, lokale Einstellungen zu berücksichtigen (Dar-
stellungen von Zeichen oder Datumsangaben oder die Darstellung numerischer Werte). Die
einzelnen Bereiche werden als Kategorien bezeichnet, die wiederum in Facetten (Spezialisie-
rungen der entsprechenden Template-Klassen) untergliedert werden. Mit Hilfe der Klasse
locale und ihrer Methoden können verschiedene lokale Einstellungen und ihre Kategorien
oder Facetten erstellt und ausgewählt werden.

344
locale

Enthaltene Klassen
locale // Klasse zur Verwaltung lokaler Einstellungen.
codecvt // Kategorie ctype. Unterstützt die Konvertierung
// zwischen Codierungsformen.
codecvt_base // Definiert Aufzählungstyp für Ergebniswerte.
codecvt_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
collate // Klasse zur gleichnamigen Kategorie. Unterstützt den
// Vergleich und die Aufspaltung von Zeichenketten.
collate_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
ctype // Klasse zur gleichnamigen Kategorie. Unterstützt die
// Zeichenerkennung sowie das Einlesen und
// Formatieren von Zeichenketten.
ctype<char> // Spezialisierung für den Datentyp char.
ctype_base // Definiert Bitfeld zur Zeichenklassifizierung.
ctype_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
ctype_byname<char> // Spezialisierung für den Datentyp char.
messages // Klasse zur gleichnamigen Kategorie. Unterstützt das
// Herauslesen von strings aus Botschaftskatalogen.
messages_base // Definiert den Datentyp catalog.
messages_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
money_base // Definiert Aufzählunstyp part zur Formatierung von
// Währungsangaben und den Rückgabetyp pattern.
moneypunct // Kategorie monetary. Unterstützt die Punktsetzung
// in Währungsangaben.
moneypunct_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
money_get // Kategorie monetary. Unterstützt das Einlesen
// von Währungsangaben.
money_put // Kategorie monetary. Unterstützt die formatierte
// Ausgabe von Währungsangaben.
numpunct // Kategorie numeric. Unterstützt die Punktsetzung
// in numerischen Werten.
numpunct_byname // Auswahl spezifischer Implementierungen anhand des
// Namens der lokalen Einstellung.
num_get // Kategorie numeric. Unterstützt das Einlesen
// numerischer Werte.
num_put // Kategorie numeric. Unterstützt die Formatierung
// bei der Ausgabe numerischer Werte.
time_base // Aufzählungstyp zur Abfolge von Datumsangaben.
time_get // Kategorie time. Unterstützt das Einlesen von
// Zeitangaben in eine Variable des Typs tm.
time_get_byname // Auswahl spezifischer Implementierungen anhand
// des Namens der lokalen Einstellung.
time_put // Kategorie time. Unterstützt die Ausgabe von
// Zeitangaben.
time_put_byname // Auswahl spezifischer Implementierungen anhand
// des Namens der lokalen Einstellung.

345
Die C++-Standardbibliothek

Funktionentemplates
has_facet() // Testet, ob eine bestimmte Facette verfügbar ist
use_facet() // Auswahl einer Facette zu einer locale-Einstellung.
is... // Methoden zur Zeichenklassifizierung (siehe C-Header
// ctype.h)
tolower() // Umwandlung in Kleinbuchstaben.
toupper() // Umwandlung in Großbuchstaben.

map
Beschreibung
Definiert die Klassentemplates map und multimap, die Container zur Verwaltung von Objekten
beliebiger Datentypen implementieren. Zusätzlich sind Funktionen (swap()) und Operatoren
zur Anwendung auf map- und multimap-Objekte definiert.

Die enthaltenen Funktionen und Klassen


map // Datenstruktur, die mit Hilfe von eindeutigen Schlüsseln
// auf ihre Elemente zugreift (ideales Hashing).
multimap // Datenstruktur, die mit Hilfe von nicht unbedingt
// eindeutigen Schlüsseln auf ihre Elemente zugreift.
swap() // Zum Vertauschen der Elemente zweier map- oder
// multimap-Container.

Überladene Operatoren
==, <, !=, > , >=, <=

Beispiel
#include <map>
#include <string>
using namespace std;

class demo;
map<int, string> container; // map-Container für string-Objekte
mit int-Schlüssel
map<int, demo> container; // map-Container für demo-Objekte
mit int-Schlüssel

346
memory

memory
Beschreibung
Enthält verschiedene Klassen- und Funktionenstemplates zur Speicherverwaltung. Die meisten
dieser Elemente sind für die Implementierung eigener Container und Algorithmen gedacht.

Enthaltene Klassentemplates
allocator // Klasse zur Implementierung von Speichermanagern.
allocator<void> // Spezialisierung für void
auto_ptr // Zeigeklasse zur automatischen Freigabe
// dynamischen Speichers.
raw_storage_iterator // Zur Ablage in nicht initialisierten
// Speicherbereichen.

Enthaltene Funktionentemplates
get_temporary_buffer() // Temporären Speicher anfordern.
return_temporary_buffer() // Auf temporären Speicher zugreifen
uninitialized_copy() // Nicht-initialisierten Speicher füllen
uninitialized_fill() // Nicht-initialisierten Speicher füllen
uninitialized_fill_n() // Nicht-initialisierten Speicher füllen

Für allocator überladene Operatoren


==, !=

Verweise
Siehe Praxisteil, Kategorie Zeiger und dynamische Speicherverwaltung, auto_ptr

new
Beschreibung
Enthält die überladenen Operatorfunktionen für new und delete, sowie verschiedene Hilfsele-
mente.

Überladene Operatoren
new // Speicher reservieren
new[] // Speicher für Feld reservieren
delete // Speicher freigeben
delete[] // Speicher für Feld freigeben

347
Die C++-Standardbibliothek

Enthaltene Hilfselemente
bad_alloc // Für Exception-Objekte, die bei gescheiterten
// Speicherreservierungen ausgelöst werden.
nothrow_t // Strukturtyp zur Übergabe an new-Operator.
nothrow // Hilfsstruktur als Argument für new
set_new_handler() // Fehlerbehandlungsroutine für new registrieren.

Verweise
Siehe Kategorie Operatoren, Die Operatoren new und delete

numeric
Beschreibung
Enthält verschiedene Funktionentemplates zur Ausführung numerischer Algorithmen auf Con-
tainer-Elementen.

Die enthaltenen Funktionen und Klassen


accumulate() // Summe berechnen
adjacent_difference() // Differenz zuweisen
inner_product() // Skalarprodukt berechnen
partial_sum() // Summe berechnen

Beispiel
#include <numeric>
#include <vector>
#include <iostream>
using namespace std;

vector<int> container;

int main() {
for(int i = 0; i < 7; i++)
container.push_back(i);

cout << "Summe der Werte: "


<< accumulate([Link](), [Link](), 0)
<< endl;

return 0;
}

348
ostream

ostream
Beschreibung
Enthält das Klassentemplate basic_ostream zur Unterstützung von Schreiboperationen auf
Streams, zwei Instanziierungen des Templates für die Datentypen char und wchar_t, die man in
Programmen direkt verwenden kann und verschiedene Manipulatoren.

Enthaltene Templates
basic_ostream // Stellt HighLevel-Routinen zum Schreiben in
// einem Stream zur Verfügung.
endl // Manipulator: Zeilenende
ends // Manipulator: Stringende
flush // Streampuffer leeren

Enthaltene Klassen
ostream // Spezialisierung für Datentyp char
wostream // Spezialisierung für Datentyp wchar_t

Beispiel
filebuf datei; // Datei zum Lesen und Schreiben
[Link]("[Link]",ios_base::in | ios_base::out); // öffnen
istream dat_ein(&datei); // Datei mit Eingabe-Stream verbinden
ostream dat_aus(&datei); // Datei mit Ausgabe-Stream verbinden

Verweise
Siehe Kategorie Ein- und Ausgabe, Streampuffer teilen

queue
Beschreibung
Definiert die Klassentemplates queue und priority_queue, die Container zur Verwaltung von
Objekten beliebiger Datentypen implementieren. Zusätzlich sind Operatoren zur Anwendung
auf queue-Objekte definiert.

Die enthaltenen Funktionen und Klassen


queue // Warteschlange. Datenstruktur, die das Einfügen von
// Elementen nur am Ende und das Entfernen von
// Elementen nur am Anfang zuläßt.
priority_queue // Datenstruktur, die das Einfügen neuer Elemente
// erlaubt und bei Pop-Zugriffen stets das Element
// höchster Priortät (beispielsweise das größte
// Element) löscht.

349
Die C++-Standardbibliothek

Überladene Operatoren
==, <, !=, > , >=, <=

Beispiel
#include <queue>
using namespace std;

class demo;
queue<int> container(5); // queue-Container für int-Objekte
queue<demo> container(5); // queue-Container für demo-Objekte

set
Beschreibung
Definiert die Klassentemplates set und multiset, die Container zur Verwaltung von Objekten
beliebiger Datentypen implementieren. Zusätzlich sind Funktionen (swap()) und Operatoren
zur Anwendung auf set- und multiset-Objekte definiert.

Die enthaltenen Funktionen und Klassen


set // Datenstruktur, in der Elemente automatisch nach ihren
// Werten geordnet werden. Ermöglicht schnelles Auffinden
// der Elemente.
multiset // Datenstruktur, die mit nicht unbedingt eindeutigen
// Werten arbeitet. Ermöglicht schnelles Auffinden der
// Elemente.
swap() // Zum Vertauschen der Elemente zweier set-Container.

Überladene Operatoren
==, <, !=, > , >=, <=

Beispiel
#include <set>
using namespace std;

class demo;
// set-Container für int-Objekte, sortiert mit < -Operator
set<int> container(5);
// set-Container für demo-Objekte, sortiert nach greater<demo>
set<demo, greater<demo> > container(5);

350
sstream

sstream
Beschreibung
Enthält Klassentemplates, die die Verbindung zwischen Strings und Streams herstellen, sowie
Instanziierungen der Templates für die Zeichentypen char und wchar_t. Stringstreams können
wie die C-Funktionen sprintf() und sscanf() eingesetzt werden.

Enthaltene Klassentemplates
basic_stringstream // Stellt HighLevel-Routinen zum Einlesen und
// Schreiben aus und in basic_string-Objekten zur
// Verfügung.
basic_istringstream // Stellt HighLevel-Routinen zum Einlesen aus
// basic_string-Objekten zur Verfügung.
basic_ostringstream // Stellt HighLevel-Routinen zum Schreiben in
// basic_string-Objekten zur Verfügung.
basic_stringbuf // Von basic_streambuf abgeleitete Pufferklasse
// für Objekte der Klasse basic_string.

Enthaltene Klassen
stringstream // typedef basic_stringstream<char> stringstream
wstringstream // typedef basic_stringstream<wchar_t> wstringstream
istringstream // typedef basic_istringstream<char> istringstream
wistringstream // typedef basic_istringstream<wchar_t> wistringstream
ostringstream // typedef basic_ostringstream<char> ostringstream
wostringstream // typedef basic_ostringstream<wchar_t> wostringstream
stringbuf // typedef basic_stringbuf<char> stringbuf
wstringbuf // typedef basic_stringbuf<wchar_t> wstringbuf

stack
Beschreibung
Definiert das Klassentemplate stack, das einen Container zur Verwaltung von Objekten beliebi-
ger Datentypen implementiert. Zusätzlich sind Operatoren zur Anwendung auf stack-Objekte
definiert.

Die enthaltenen Funktionen und Klassen


stack // Keller. Datenstruktur, die Einfügen und Löschen jeweils
// nur am oberen Ende erlaubt.

Überladene Operatoren
==, !=, <, >, >=, <=

351
Die C++-Standardbibliothek

Beispiel
#include <stack>
using namespace std;

class demo;
stack<int> container(5); // stack-Container für int-Objekte
stack<demo> container(5); // stack-Container für demo-Objekte

stdexcept
Beschreibung
Definiert eine Reihe von Exceptions für Fehlermeldungen in C++-Programmen.

Enthaltene Exception-Klassen
domain_error // Für Exception-Objekte, die bei Auftreten
// unzulässiger Werte ausgelöst werden.
invalid_argument // Für Exception-Objekte, die bei Übergabe ungültiger
// Argumente ausgelöst werden.
length_error // Für Exception-Objekte, die ausgelöst werden, wenn
// die zulässige Größe von Datenstrukturen oder
// -typen überschritten wird.
logic_error // Für Exception-Objekte, die logische Fehler betreffen.
out_of_range // Für Exception-Objekte, die ausgelöst werden, wenn ein
// Argument nicht im vorgesehenen Bereich liegt.
overflow_error // Für Exception-Objekte, die bei arithmetischen
// Überläufen ausgelöst werden.
range_error // Für Exception-Objekte, die bei Verletzung von
// Gültigkeitsbereichen ausgelöst werden.
runtime_error // Für Exception-Objekte, die Laufzeitfehler betreffen.
underflow_error // Für Exception-Objekte, die bei arithmetischen
// Unterläufen ausgelöst werden.

streambuf
Beschreibung
Enthält das Template für die Streampuffer-Klassen, sowie zwei Instanziierungen des Templates
für die Datentypen char und wchar_t. Die Stream-Klassen verwenden Instanzen der Pufferklas-
sen für die eigentlichen Schreib- und Leseoperationen (dabei müssen die Ein- und Ausgaben
nicht wirklich gepuffert sein; der interne Puffer der Pufferklassen kann auch auf NULL gesetzt
sein).

352
string

Enthaltene Klassentemplates
basic_streambuf // Basisklasse für gepufferte LowLevel-Operationen.

Enthaltene Klassen
streambuf // typedef basic_streambuf<char> streambuf
wstreambuf // typedef basic_streambuf<wchar_t> wstreambuf

Verweise
Siehe Kategorie Ein- und Ausgabe, Pufferung

string
Beschreibung
Enthält das Klassentemplate basic_string, das alle wichtigen Methoden für die Programmie-
rung mit Strings bereitstellt, Instanziierungen des Templates für die Zeichentypen char und
wchar_t, sowie Operatoren und Funktionen für die Arbeit mit Strings.

Enthaltene Elemente
basic_string // Klassentemplate zur String-Behandlung.
char_traits // Klasse, die die Charkteristika eines
// Zeichentyps beschreibt
char_traits<char> // Spezialisierung für Datentyp char
char_traits<wchar_t> // Spezialisierung für Datentyp wchar_t
getline() // Zeile einlesen
swap() // Zum Vertauschen der Zeichen zweier Strings
string // Spezialisierung von basic_string für Datentyp char
wstring // Spezialisierung von basic_string für Datentyp wchar_t

Für basic_string überladene Operatoren


+, ==, !=, <, >, <=, >=

Für basic_istream überladene Operatoren


>>, <<

Verweise
Siehe Kategorie Zeichenketten, Programmieren mit der Klasse string

353
Die C++-Standardbibliothek

typeinfo
Beschreibung
Enthält die Klasse type_info, mit deren Hilfe RTTI-Informationen in C++-Programmen zur Ver-
fügung gestellt werden, sowie zwei Exception-Klassen für die Fehlerbehandlung.

Enthaltene Klassen
type_info // Verwaltet Informationen (beschreibender String,
// Prioritätswert) zu Datentypen.
bad_cast // Für Exception-Objekte, die bei gescheiterten
// dynamic_cast-Operationen ausgelöst werden.
bad_typeid // Für Exception-Objekte, die ausgelöst werden, um einen
// Null-Zeiger in typeid-Ausdrücken anzuzeigen.

Verweise
Siehe Kategorie Vererbung und Polymorphie, RTTI – Laufzeittypidentifizierung

utility
Beschreibung
Enthält Templates, die die Arbeit mit Wertepaaren erleichtern und innerhalb der C++-Laufzeit-
bibliothek verwendet werden.

Enthaltene Templates
pair // Template-Klasse für Strukturen mit zwei Elementen
// unterschiedlicher Datentypen.
make_pair() // Funktion, die aus ihren zwei Argumenten ein pair erzeugt.

Überladene Operatoren
==, <, !=, >, >=, <=

valarray
Beschreibung
Definiert die Datenstruktur valarray, die ihre Elemente wie in einem Array verwaltet (der Spei-
cher wird allerdings dynamisch verwaltet). Die Klasse valarray erlaubt eine Vielzahl von Ope-
rationen, die jeweils auf sämtlichen Elementen des Arrays ausgeführt werden, sowie die
Möglichkeit, mit Hilfe der Hilfsklassen Teilmengen zu bilden.

354
valarray

Enthaltene Klassentemplates und Klassen


valarray // Eindimensionales dynamisches Array mit einer Vielzahl
// von Operationen, die gleichzeitig auf allen Elementen
// ausgeführt werden
gslice // Hilfsklasse zur Definition einer mehrdimensionalen
// Teilmenge aus einem eindimensionalen valarray-Objekt.
gslice_array // Hilfsklasse zur Manipulation einer mehrdimensionalen
// Teilmenge aus einem eindimensionalen valarray-Objekt.
// Die Teilmenge wird mittels gslice erzeugt.
indirect_array // Hilfsklasse zur Manipulation einer Teilmenge
// eines valarray-Objekts. Die Teilmenge wird
// mittels eines Index-Arrays erzeugt.
mask_array // Hilfsklasse zur Manipulation einer Teilmenge eines
// valarray-Objekts. Die Teilmenge wird mittels einer
// Maske erzeugt.
slice // Hilfsklasse zur Definition einer Teilmenge konstanter
// Schrittweite aus einem valarray-Objekt.
slice_array // Hilfsklasse zur Manipulation einer Teilmenge
// konstanter Schrittweite aus einem valarray-Objekt.
// Die Teilmenge wird mittels slice erzeugt.

Für valarray überladene Funktionen


abs atan2 log pow tan
acos cos log10 sin tanh
asin cosh min sinh
atan exp max sqrt

Für valarray überladene Operatoren


*, /, %, +, –, ^, &, <<, >>, &&, ==, !=, <, >, <=, >=

Beispiel
#include <iostream>
#include <string>
#include <valarray>
using namespace std;

int main()
{
valarray<int> va(20);
for(int i = 0; i < 20; i++)
{
va[i] = i;
cout << va[i] << endl;
}

valarray<int> teil(5);
valarray<size_t> size(2);

355
Die C++-Standardbibliothek

size[0] = 3; size[1] = 4;
valarray<size_t> stride(2);
stride[0] = 5; stride[1] = 1;

teil = va[gslice(2,size,stride)];
cout << "\nTeilarray\n";
for(int i = 0; i < size[0]*size[1]; i++)
{
cout << teil[i] << endl;
}
return 0;
}

vector
Beschreibung
Definiert das Klassentemplate vector, das einen Container zur Verwaltung von Objekten belie-
biger Datentypen implementiert. Zusätzlich sind Funktionen (swap()) und Operatoren zur
Anwendung auf vector-Objekte definiert.

Die enthaltenen Funktionen und Klassen


vector // Standard-Datenstruktur, die für Einfügen/Löschen am
// Ende optimiert ist und schnellen direkten Zugriff
// auf beliebige Positionen zuläßt.
vector<bool> // Vordefinierte Spezialisierung des Klassentemplates
// vector, die eine optimierte Speicherverwaltung
// garantiert.
swap() // Zum Vertauschen der Elemente zweier vector-Container.

Überladene Operatoren
==, !=, <, >, >=, <=

Beispiel
#include <vector>
using namespace std;

class demo;
vector<int> container(5); // vector-Container für int-Objekte
vector<demo> container(5); // vector-Container für demo-Objekte

356
Allgemeine Eigenschaften

Die Container-Klassen

Allgemeine Eigenschaften
Beschreibung
Die Container-Klassen sollen dem Programmierer die Verwaltung größerer Datenmengen in
seinen Programmen erleichtern. Sie stellen somit eine komfortable Alternative zu den Arrays
und dynamischen Feldern dar und ersparen dem Programmierer die Implementierung eigener
höherer Datenstrukturen.
● Container können für Objekte elementarer oder selbst definierter Klassenty-
pen eingerichtet werden. Voraussetzung ist allerdings, daß Kopierkonstruktor
und Zuweisungsoperator des Klassentyps nicht durch private- oder protected-
Deklaration unzugänglich gemacht wurden. Weiterhin müssen für bestimmte
Aktionen auf den Elementen eines Containers die entsprechenden Operatoren
für den Klassentyp der Objekte überladen sein (beispielsweise die Vergleichs-
operatoren).
● In einem Container können nur Objekte eines Datentyps gespeichert werden.
● Der Container ermöglicht den Zugriff sowie das Einfügen und Löschen von
Objekten. Das Löschen des Containers impliziert auch das Löschen der in ihm
enthaltenen Objekte (handelt es sich dabei um Zeiger, werden natürlich nur
die Zeiger und nicht die Objekte, auf die die Zeiger verweisen, gelöscht).
● Der Container definiert nur die Methoden zur Verwaltung der Objekte nicht
zu deren Bearbeitung. Letzterem Zweck dienen die Algorithmen.
● Die verschiedenen Containertypen sind als Templates definiert, die für den
Datentyp der aufzunehmenden Objekte spezialisiert werden müssen.
● Die Größe eines Containers (sprich die Anzahl der Objekte, die er aufnehmen
kann) ist nicht statisch festgelegt. Zu diesem Zweck implementiert jeder Con-
tainer eine eigene dynamische Speicherverwaltung.
● Die einzelnen Containertypen unterscheiden sich in der Art und Weise, wie sie
die Daten verwalten (sortiert – unsortiert; geordnet – ungeordnet), welche
Möglichkeiten des Zugriffs sie gestatten (Zugriff am Anfang oder Ende der
Datenstruktur, indizierter Zugriff, etc.), welche Möglichkeiten des Zugriffs
besonders effizient sind.

Grundeigenschaften von Containern


Obwohl die Klassentemplates der verschiedenen Container nicht auf ein gemeinsa-
mes Basisklassentemplate zurückgehen, gibt es eine Reihe von Eigenschaften, die
allen Containertypen gemeinsam sind.

357
Die C++-Standardbibliothek

Allgemeine Container-Eigenschaften
Bei dieser und den folgenden Auflistungen bezeichnet X einen beliebigen Contai-
nertyp, a und b sind Container, i und j Iteratoren.

Eigenschaft Beschreibung
X() Erzeugt einen anonymen Container der Größe 0
Xa Erzeugt den Container a der Größe 0
X a(b)
X a = b; Erzeugt a als Kopie von b
(&a)->~X() Destruktor wird auf alle Elemente angewendet
[Link]() Liefert Iterator auf erstes Element in Container
[Link]() Liefert Iterator hinter letztes Element
[Link]() Liefert die aktuelle Anzahl an Elementen
[Link]() Gibt an, ob der Container leer ist
[Link](b) Vertauscht die Elemente der Container a und b
a == b true, wenn beide Container gleich viele Elemente enthalten, die paarweise
gleich sind
a != b !(a == b)
a<b Lexikographischer Vergleich von a und b
a>b Lexikographischer Vergleich von a und b
a <= b !(a > b)
a >= b !(a < b)

Sequentielle und assoziative Container


Jeder Containertyp hat seine eigenen Spezialitäten und Qualitäten. Unabhängig von
diesen individuellen Besonderheiten lassen sich die Container in zwei Gruppen ein-
teilen, die sich in der Anordnung der in ihnen verwahrten Objekte unterscheiden:
sequentielle und assoziative Container.
Sequentielle Container
● In einem sequentiellen Container werden die Elemente in linearer Folge ange-
ordnet (beispielsweise als Array, Liste oder eine Kombination aus beidem).
● Die Anordnung richtet sich nach dem Zeitpunkt, bzw. dem Ort des Einfügens
der einzelnen Elemente.
● Die lineare Anordnung erlaubt Operationen wie das Einfügen an einer be-
stimmten Position oder das Löschen eines bestimmten Bereichs von Elemen-
ten.
● Sequentielle Container arbeiten mit Forward-Iteratoren oder höheren.
Sequentielle Container sind vector, list, deque, queue, priority_queue und stack.

358
Allgemeine Eigenschaften

Eigenschaft Beschreibung
X(n,t) Erzeugt Container mit n Kopien des Werts t
X a(n,t)
X(i,j) Erzeugt Container als Kopie der Folge [i,j) (mit i, ohne j)
X a(i,j)
[Link](p, ) Fügt vor eine Position p ein; entweder einen Wert t, n Kopien eines
Werts t oder eine Kopie der Folge [i,j)
[Link](p) Löscht das Element an der Position p
[Link](i,j) Löscht die Elemente im Bereich [i,j)
[Link]() Löscht alle Elemente im Container

Die folgenden Operationen werden nur von den sequentiellen Containern unter-
stützt, für die sie in konstanter Zeit implementiert werden können:

Operation Beschreibung für die Container


[Link]() *[Link]() vector, list, deque
[Link]() *--[Link]() vector, list, deque
a.push_front(t) [Link]([Link](),t) list, deque
a.push_back(t) [Link]([Link](),t) vector, list, deque
a.pop_front() [Link]([Link]()) list, deque
a.pop_back() [Link](--[Link]()) vector, list, deque
a[n] *([Link]() + n) vector, deque
[Link](n) *([Link]() + n) vector, deque

Entsprechend der internen Speicherverwaltung lassen sich – wie der Tabelle zu ent-
nehmen ist – nicht alle dieser Operationen für alle sequentiellen Container imple-
mentieren. Für einen vector-Container, der einem dynamischen Array sehr nahe
kommt, würde beispielsweise das Einfügen am Containeranfang (push_front())
erfordern, daß zuerst alle Elemente im Container, vom Containerende angefangen,
um eine Position nach hinten gerückt werden. Da dies nur in linearer und nicht in
konstanter Zeit zu schaffen ist, wird diese Operation von vector nicht unterstützt.
Assoziative Container
● In einem assoziativen Container werden die Elemente sortiert verwahrt (die
zugrundeliegende Datenstruktur kann dabei ein binärer Baum oder eine
Hashing-Tabelle sein).
● Die Sortierung richtet sich nach den Schlüsseln (keys) der Elemente und nach
einem bestimmten Sortierkriterium, dem Vergleichsobjekt (Compare).
● Für set und multiset fallen Wert und Schlüssel zusammen, d. h., der Wert ist
gleichzeitig auch der Schlüssel, nach dem sortiert wird.

359
Die C++-Standardbibliothek

● Für map und multimap wird jedem Element ein eigener Schlüssel zugewiesen,
und Element und Schlüssel werden im Container als Paar verwahrt.
● Die Sortierung erlaubt das schnelle Auffinden von Elementen nach ihrem Wert
oder einem zugehörigen Schlüssel.
● Assoziative Container arbeiten mit bidirektionalen Iteratoren.
● Assoziative Container sind set, multiset, map und multimap.

Eigenschaft Beschreibung
X(c) Pendants zu den Konstruktoren der sequentiellen Container, die als
X a(c) zusätzliches Argument ein Compare-Objekt als Vergleichskriterium
X(i,j,c) übernehmen. Ohne Compare-Objekt aufgerufen, wird das Standard-
X a(i,j,c) vergleichsobjekt des Containers (siehe Template-Definition) ver-
wendet.
[Link](... ) Verschiedene überladene Versionen zum Einfügen von Elementen in
den Container
[Link](... ) Verschiedene überladene Versionen zum Löschen von Elementen aus
dem Container
[Link]() Löscht alle Elemente im Container
[Link](k) Liefert einen Iterator auf das erste Element mit Schlüssel k
[Link](k) Liefert die Anzahl der Elemente mit Schlüssel k
a.lower_bound(k) Liefert einen Iterator auf das erste Element, dessen Schlüssel nicht
kleiner als k ist
a.upper_bound(k) Liefert einen Iterator auf das erste Element, dessen Schlüssel größer
als k ist
a.equal_range(k) Liefert die Iteratoren von lower_bound() und upper_bound() als Paar
(siehe make_pair() )

bitset
Flags verwalten (aus Header bitset)

Beschreibung
Die Klasse bitset dient zur Verwaltung einer bestimmten Zahl von Elementen (Bits), die nur
Werte von Null oder Eins annehmen.

Anwendung
Instanzen der Klasse bitset können zur übersichtlichen Verwaltung von Diagnose-
und Schaltervariablen (Flags) herangezogen werden. Gegenüber dem Einsatz der
von C stammenden Bitoperatoren oder der Bitfelder bieten die für bitset zur Verfü-
gung stehenden Methoden und Operatoren mehr Komfort.

360
bitset

Die Anzahl der Bits im Bitset ist unveränderlich und wird durch den Platzhalter N
bei der Spezialisierung des Templates festgelegt. Zur Verwaltung einer variablen
Zahl von Flags kann man auf den Container vector<bool> zurückgreifen.
bitset<4> options; // Bits initialisieren
Die einzelnen Bits im Bitset können direkt bei der Erzeugung des Bitsets mit den
Werten aus einem Integer oder einem String initialisiert werden.
bitset<4> options("0100");
Die Funktionen to_ulong() und to_string() wandeln in umgekehrter Weise ein
Bitset in einen Integer-Wert oder ein String-Objekt um. Die Funktionen set(),
reset(), flip() können zum Setzen aller Bits oder eines bestimmten Bits verwendet
werden. Zur Abfrage einzelner Bits dient die Funktion test(). Zur Manipulation
einzelner Bits ist zudem der Index-Operator [ ] implementiert. Die Operatoren &=,
|= und ^= verwenden ein zweites Bitset zur Manipulation ihrer Instanz.

Warnung
Die Klasse bitset fällt aus dem Rahmen der anderen Container (unterstützt keine
Iteratoren, verfügt nicht über die Grundeigenschaften, etc.).

Referenz
template<size_t N> class bitset {
public:
class reference {
friend class bitset;
reference();
public:
~reference();
reference& operator=(bool x); // für b[i] = x;
reference& operator=(const reference&); // für b[i] = b[j];
bool operator~() const; // dreht das Bit um
operator bool() const; // für x = b[i];
reference& flip(); // für b[i].flip();
};
// Konstruktoren:
bitset();
bitset(unsigned long val);
template<class charT, class traits, class Allocator>
explicit bitset(
const basic_string<charT,traits,Allocator>& str,
typename basic_string<charT,traits,Allocator>::size_type pos = 0,
typename basic_string<charT,traits,Allocator>::size_type n =
basic_string<charT,traits,Allocator>::npos);
// Operatoren:
bitset<N>& operator&=(const bitset<N>& rhs);
bitset<N>& operator|=(const bitset<N>& rhs);
bitset<N>& operator^=(const bitset<N>& rhs);

361
Die C++-Standardbibliothek

bitset<N>& operator<<=(size_t pos);


bitset<N>& operator>>=(size_t pos);
bitset<N>& set();
bitset<N>& set(size_t pos, int val = true);
bitset<N>& reset();
bitset<N>& reset(size_t pos);
bitset<N> operator~() const;
bitset<N>& flip();
bitset<N>& flip(size_t pos);
reference operator[](size_t pos); // for b[i];

unsigned long to_ulong() const;


template <class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator> to_string() const;
size_t count() const;
size_t size() const;
bool operator==(const bitset<N>& rhs) const;
bool operator!=(const bitset<N>& rhs) const;
bool test(size_t pos) const;
bool any() const;
bool none() const;
bitset<N> operator<<(size_t pos) const;
bitset<N> operator>>(size_t pos) const;
};

Verweise
Siehe Header-Datei bitset

deque
Sequentieller Container (aus Header deque)

Beschreibung
Die Abkürzung deque steht für double ended queue. Dahinter verbirgt sich eine Datenstruktur,
die üblicherweise auf einer Verkettung von Array-Blöcken basiert und ihre Elemente in einer
sequentiellen Folge anordnet.
Die Klasse deque gleicht der Klasse vector und bietet wie diese schnellen direkten Zugriff auf
einzelne Elemente ([]-Operator, Methode at()) sowie Einfügen und Löschen von Elementen an
beliebigen Positionen (insert(), erase()). Anders als der Zugriff auf bestehende Elemente ist
das Einfügen oder Löschen von Elementen allerdings recht zeitaufwendig, da diese Operationen
meist mit dem internen Umkopieren der Elemente im Container verbunden ist. Lediglich am
Anfang oder Ende der Datenstruktur kann in konstanter Zeit eingefügt oder gelöscht werden.

362
deque

Im Verleich zu vector ist der Zugriff auf beliebige Positionen etwas langsamer, dafür ist die
Speicherverwaltung meist günstiger.
Im Vergleich zu einem list-Container ist das Einfügen und Löschen an mittleren Positionen
zeitaufwendiger, dafür erlaubt deque den bequemen indizierten Zugriff auf bestimmte Positio-
nen (zum Lesen oder Schreiben).
Iteratoren für deque-Container sollten mindestens der forward_iterator-Kategorie angehören,
verschiedene Funktionen verlangen aber höhere Iteratorenkategorien. Einfüge- und Löschope-
rationen in der Mitte des Containers führen stets zur Ungültigkeit bestehender Iteratoren und
Referenzen auf Container-Elemente.

Anwendung
Hinter deque steht ein Klassentemplate, aus dem man zuerst eine Container-Klasse
erzeugt. Dabei übergibt man dem ersten Template-Parameter T den Datentyp der zu
verwaltenden Objekte.
deque<int> container;
Die überladenen Formen der Konstruktoren erlauben die Einrichtung leerer Contai-
ner oder Container, die mehrere Kopien eines Elements bzw. die Kopie einer
Sequenz von Elementen aus einem anderen Container enthalten.
Neue Elemente können mittels insert(), push_front(), push_back(), resize() oder
assign() eingefügt werden, wobei letztere Funktion den Container zuvor leert.
Bestehende Elemente können mittels erase(), pop_front(), pop_back(), resize()
oder clear() gelöscht werden.
Zugriff auf einzelne Elemente kann mit Hilfe zurückgelieferter Iteratoren geschehen
(begin(), end(), rbegin(), rend() sowie insert() ) oder über zurückgegebene Refe-
renzen (Operator [], at(), front(), back() ).
Schließlich ist es möglich, über die globalen Funktionen der Header-Datei <algo-
rithm> Container zu manipulieren, zu sortieren, in ihnen zu suchen, etc.

Referenz
template <class T, class Allocator = allocator<T> >
class deque {
public:
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef T value_type;
typedef Allocator allocator_type;
typedef typename Allocator::pointer pointer;

363
Die C++-Standardbibliothek

typedef typename Allocator::const_pointer const_pointer;


typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
// Konstruktoren und Zuweisung:
explicit deque(const Allocator& = Allocator());
explicit deque(size_type n, const T& value = T(),
const Allocator& = Allocator());
template <class InputIterator>
deque(InputIterator first, InputIterator last,
const Allocator& = Allocator());
deque(const deque<T,Allocator>& x);
~deque();
deque<T,Allocator>& operator=(const deque<T,Allocator>& x);
template <class InputIterator>
void assign(InputIterator first, InputIterator last);
template <class Size, class T>
void assign(Size n, const T& t = T());
allocator_type get_allocator() const;
// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Größe:
size_type size() const;
size_type max_size() const;
void resize(size_type sz, T c = T());
bool empty() const;
// Zugriff auf Elemente:
reference operator[](size_type n);
const_reference operator[](size_type n) const;
reference at(size_type n);
const_reference at(size_type n) const;
reference front();
const_reference front() const;
reference back();
const_reference back() const;
// Einfügen, Löschen:
void push_front(const T& x);
void push_back(const T& x);
iterator insert(iterator position, const T& x = T());
void insert(iterator position, size_type n, const T& x);
template <class InputIterator>
void insert(iterator position,InputIterator first,
InputIterator last);
void pop_front();

364
list

void pop_back();
iterator erase(iterator position);
iterator erase(iterator first, iterator last);
void swap(deque<T,Allocator>&);
void clear();
};

list
Sequentieller Container (aus Header list)

Beschreibung
Das Klassentemplate list repräsentiert wie deque und vector einen sequentiellen Container
mit direktem Zugriff auf das erste und letzte Element sowie Einfügen und Löschen von Elemen-
ten an beliebigen Positionen.
Das Einfügen und Löschen von Elementen an beliebigen Positionen innerhalb des Containers
erfolgt für list schneller als für deque oder vector, da diese Operationen nicht mit dem Ver-
schieben der nachfolgenden Elemente verbunden ist. Dafür fehlt list der indizierte Zugriff auf
Elemente an einer bestimmten Position.
Iteratoren für list-Container sollten mindestens der forward_iterator-Kategorie angehören,
verschiedene Funktionen verlangen aber höhere Iteratorenkategorien. Einfüge- und Löschope-
rationen beeinträchtigen nicht die Gültigkeit bestehender Iteratoren und Referenzen auf Con-
tainer-Elemente.

Anwendung
Hinter list steht ein Klassentemplate, aus dem man zuerst eine Container-Klasse
erzeugt. Dabei übergibt man dem ersten Template-Parameter T den Datentyp der zu
verwaltenden Objekte.
list<int> container;
Die überladenen Formen der Konstruktoren erlauben die Einrichtung leerer Contai-
ner oder Container, die mehrere Kopien eines Elementes bzw. die Kopie einer
Sequenz von Elementen aus einem anderen Container enthalten.
Neue Elemente können mittels insert(), push_front(), push_back(), resize(),
assign() oder merge() eingefügt werden.
Bestehende Elemente können mittels erase(), pop_front(), pop_back(), resize(),
clear(), unique() oder remove(), remove_if() gelöscht werden.
Der Zugriff auf einzelne Elemente kann mit Hilfe zurückgelieferter Iteratoren
geschehen (begin(), end(), rbegin(), rend() sowie insert()) oder über zurückgege-
bene Referenzen (front(), back()).

365
Die C++-Standardbibliothek

Mittels der Funktion sort() können die Elemente sortiert werden, wobei die Art
der Sortierung durch den <-Operator oder eine selbstdefinierte Vergleichsfunktion
bestimmt werden kann. Mittels reverse() kann die Reihenfolge umgekehrt werden.
Schließlich ist es möglich, über die globalen Funktionen der Header-Datei <algo-
rithm> Container zu manipulieren, zu sortieren, in ihnen zu suchen, etc.

Referenz
template <class T, class Allocator = allocator<T> >
class list {
public:
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef T value_type;
typedef Allocator allocator_type;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
// Konstruktoren und Zuweisung:
explicit list(const Allocator& = Allocator());
explicit list(size_type n, const T& value = T(),
const Allocator& = Allocator());
template <class InputIterator>
list(InputIterator first, InputIterator last,
const Allocator& = Allocator());
list(const list<T,Allocator>& x);
~list();
list<T,Allocator>& operator=(const list<T,Allocator>& x);
template <class InputIterator>
void assign(InputIterator first, InputIterator last);
template <class Size, class T>
void assign(Size n, const T& t = T());
allocator_type get_allocator() const;
// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Größe:
bool empty() const;

366
map und multimap

size_type size() const;


size_type max_size() const;
void resize(size_type sz, T c = T());
// Zugriff auf Elemente:
reference front();
const_reference front() const;
reference back();
const_reference back() const;
// Einfügen und Löschen:
void push_front(const T& x);
void pop_front();
void push_back(const T& x);
void pop_back();
iterator insert(iterator position, const T& x = T());
void insert(iterator position, size_type n, const T& x);
template <class InputIterator>
void insert(iterator position, InputIterator first,
InputIterator last);
iterator erase(iterator position);
iterator erase(iterator position, iterator last);
void swap(list<T,Allocator>&);
void clear();
// Operatoren:
void splice(iterator position, list<T,Allocator>& x);
void splice(iterator position, list<T,Allocator>& x, iterator i);
void splice(iterator position, list<T,Allocator>& x, iterator first,
iterator last);
void remove(const T& value);
template <class Predicate> void remove_if(Predicate pred);
void unique();
template <class BinaryPredicate> void unique(BinaryPredicate
binary_pred);
void merge(list<T,Allocator>& x);
template <class Compare> void merge(list<T,Allocator>& x,
Compare comp);
void sort();
template <class Compare> void sort(Compare comp);
void reverse();
};

map und multimap


Assoziativer Container (aus Header map)

Beschreibung
Die Container map und multimap benutzen Schlüssel, um einen schnellen Zugriff auf ihre Ele-
mente zu gewähren. Die Idee dabei ist, daß den zu verwaltenden Objekten sogenannte Schlüs-

367
Die C++-Standardbibliothek

sel beigeordnet werden (man kennt dies beispielsweise von Arrays, bei denen die einzelnen
Elemente mit Indizes verbunden sind). Ähnlich den Indizes eines Arrays soll aus den Schlüsseln
auf die Lokation des Objekts geschlossen werden können.
In den Containern werden die Elemente nach ihren Schlüsseln sortiert abgelegt. Die Sortierung
erlaubt ein schnelles Auffinden von Elementen nach ihren Schlüsseln. Der Wert eines Schlüssels
eines eingefügten Elements darf nicht geändert werden, da dies die Sortierung zerstören würde.
Iteratoren auf map und multimap müssen von der Kategorie bidirectional sein.
Während die Klasse map nur eindeutige Schlüssel erlaubt, können in multimap mehrere Schlüssel
bezüglich der Vergleichsfunktion identisch sein. Dies bedeutet, daß ein Schlüssel auf mehrere
Objekte verweist, die dann noch extra durchsucht werden müssen, um ein bestimmtes Objekt her-
auszufinden. Dies bedeutet meist verlängerte Laufzeiten bei geringerem Speicherbedarf.
Die Klasse multimap verfügt über keinen Indexoperator [].

Anwendung
Hinter map und multimap stehen Klassentemplates, aus denen man zuerst Container-
Klassen erzeugen muß. Dabei übergibt man dem Template-Parameter Key den
Datentyp der Schlüssel und dem Template-Parameter T den Datentyp der zu ver-
waltenden Objekte.
map<int, string> container;
Zusätzlich kann man als dritten Template-Parameter ein Funktionsobjekt überge-
ben, das festlegt, wie die Elemente im Container anhand der Schlüssel sortiert wer-
den sollen.
map<int, string, greater<int> > container;
Die überladenen Formen der Konstruktoren erlauben die Einrichtung leerer Contai-
ner ebenso wie von Container, die eine Sequenz von Elementen aus einem anderen
Container erhalten. Die Objekte zur Allokation und zum Vergleich können selbst
definiert werden oder aus der Vorgabe übernommen werden.
Neue Elemente können mittels insert() eingefügt werden.
Bestehende Elemente können mittels erase() oder clear() gelöscht werden.
Zugriff auf einzelne Elemente kann mit Hilfe zurückgelieferter Iteratoren geschehen
(begin(), end(), rbegin(), rend(), find(), lower_bound(), upper_bound() sowie
insert()).
Schließlich ist es möglich, über die globalen Funktionen der Header-Datei <algo-
rithm> Container zu manipulieren, zu sortieren, in ihnen zu suchen, etc.

368
map und multimap

Referenz

map <map>
template <class Key, class T, class Compare = less<Key>,
class Allocator = allocator<T> >
class map {
public:
typedef Key key_type;
typedef T mapped_type;
typedef pair<const Key, T> value_type;
typedef Compare key_compare;
typedef Allocator allocator_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef Allocator::pointer pointer;
typedef Allocator::const_pointer const_pointer;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
class value_compare
: public binary_function<value_type,value_type,bool> {
friend class map;
protected:
Compare comp;
value_compare(Compare c) : comp(c) {}
public:
bool operator()(const value_type& x, const value_type& y) const {
return comp([Link], [Link]);
}
};
// Konstruktoren und Zuweisung:
explicit map(const Compare& comp = Compare(), const Allocator& =
Allocator());
template <class InputIterator>
map(InputIterator first, InputIterator last,
const Compare& comp = Compare(), const Allocator& =
Allocator());
map(const map<Key,T,Compare,Allocator>& x);
~map();
map<Key,T,Compare,Allocator>&
operator=(const map<Key,T,Compare,Allocator>& x);
// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;

369
Die C++-Standardbibliothek

reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Groesse:
bool empty() const;
size_type size() const;
size_type max_size() const;
// Zugriff auf Elemente:
reference operator[](const key_type& x);
// Einfügen und Löschen:
pair<iterator, bool> insert(const value_type& x);
iterator insert(iterator position, const value_type& x);
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
void erase(iterator position);
size_type erase(const key_type& x);
void erase(iterator first, iterator last);
void swap(map<Key,T,Compare,Allocator>&);
void clear();
// Sonstiges:
key_compare key_comp() const;
value_compare value_comp() const;
iterator find(const key_type& x);
const_iterator find(const key_type& x) const;
size_type count(const key_type& x) const;
iterator lower_bound(const key_type& x);
const_iterator lower_bound(const key_type& x) const;
iterator upper_bound(const key_type& x);
const_iterator upper_bound(const key_type& x) const;
pair<iterator,iterator> equal_range(const key_type& x);
pair<const_iterator,const_iterator> equal_range(const key_type& x)
const;
};

multimap <map>
template <class Key, class T, class Compare = less<Key>,
class Allocator = allocator<T> >
class multimap {
public:
typedef Key key_type;
typedef T mapped_type;
typedef pair<const Key,T> value_type;
typedef Compare key_compare;
typedef Allocator allocator_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;

370
map und multimap

typedef typename Allocator::difference_type difference_type;


typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
class value_compare
: public binary_function<value_type,value_type,bool> {
friend class multimap;
protected:
Compare comp;
value_compare(Compare c) : comp(c) {}
public:
bool operator()(const value_type& x, const value_type& y) const {
return comp([Link], [Link]);
}
};
// Konstruktoren und Zuweisung:
explicit multimap(const Compare& comp = Compare(),
const Allocator& = Allocator());
template <class InputIterator>
multimap(InputIterator first, InputIterator last,
const Compare& comp=Compare(),const Allocator&=Allocator());
multimap(const multimap<Key,T,Compare,Allocator>& x);
~multimap();
multimap<Key,T,Compare,Allocator>&
operator=(const multimap<Key,T,Compare,Allocator>& x);
allocator_type get_allocator() const;
// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Groesse:
bool empty() const;
size_type size() const;
size_type max_size() const;
// Einfügen und Löschen:
iterator insert(const value_type& x);
iterator insert(iterator position, const value_type& x);
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
void erase(iterator position);
size_type erase(const key_type& x);
void erase(iterator first, iterator last);
void swap(multimap<Key,T,Compare,Allocator>&);
void clear();

371
Die C++-Standardbibliothek

// Sonstiges:
key_compare key_comp() const;
value_compare value_comp() const;
iterator find(const key_type& x);
const_iterator find(const key_type& x) const;
size_type count(const key_type& x) const;
iterator lower_bound(const key_type& x);
const_iterator lower_bound(const key_type& x) const;
iterator upper_bound(const key_type& x);
const_iterator upper_bound(const key_type& x) const;
pair<iterator,iterator> equal_range(const key_type& x);
pair<const_iterator,const_iterator> equal_range(const key_type& x)
const;
};

priority_queue
Sequentieller Container (aus Header queue)

Beschreibung
Eine priority_queue ist eine Warteschlange, die sicherstellt, daß Lese- und Löschzugriffe
immer das Element höchster Priorität betreffen.
Warteschlangen werden üblicherweise zum differenzierten Abarbeiten zeitlich geordneter Ein-
gaben/Befehle eingesetzt. Die Eingaben werden aufgrund bestimmter Eigenschaften (Größe,
Wert einer Variablen etc.) mit einer Priorität versehen. Bei der Abarbeitung überspringen dann
Eingaben höherer Priorität alle anderen Eingaben, während Eingaben gleicher Priorität in der
Reihenfolge ihres zeitlichen Auftretens bearbeitet werden.

Anwendung
Die Klasse priority_queue implementiert keinen wirklich neuen Container. Statt
dessen verwendet sie eine protected-Instanz eines sequentiellen Containers und
macht nur diejenigen Methoden dieser Containerklasse zugänglich (durch Defini-
tion eigener public-Methoden, die lediglich die entsprechenden Methoden der Con-
tainerklasse aufrufen), die für die Implementierung einer Prioritätswarteschlange
nötig sind.
Hinter priority_queue steht ein Klassentemplate, aus dem man zuerst eine Contai-
ner-Klasse erzeugen muß. Dabei übergibt man dem ersten Template-Parameter T
den Datentyp der zu verwaltenden Objekte.
priority_queue<int> container;
Zusätzlich kann man als zweiten Template-Parameter einen Container spezifizie-
ren, der intern zur Verwahrung der Elemente verwendet wird. Der übergebene
Container muß über die Methoden empty(), size(), front(), back(), push_back(),

372
queue

pop_back() verfügen und Random Access-Iteratoren unterstützen (wie beispielsweise


vector oder deque, aber nicht list). Standardmäßig wird ein vector<T>-Container
verwendet.
priority_queue<int, deque<int> > container;
Als dritten Template-Parameter kann man ein Funktionsobjekt übergeben, daß das
Sortierkriterium für die Feststellung der Priorität spezifiziert.
priority_queue<int, deque<int>, greater<int> > container;

Referenz
template <class T, class Container = vector<T>,
class Compare = less<Container::value_type> >
class priority_queue {
public:
typedef typename Container::value_type value_type;
typedef typename Container::size_type size_type;
typedef typename Container container_type;
protected:
Container c;
Compare comp;
public:
explicit priority_queue(const Compare& x = Compare(),
const Container& = Container());
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last,
const Compare& x = Compare(),
const Container& = Container());
bool empty() const { return [Link](); }
size_type size() const { return [Link](); }
const value_type& top() const { return [Link](); }
void push(const value_type& x);
void pop();
};

queue
Sequentieller Container (aus Header queue)

Beschreibung
Eine queue oder Warteschlange ist eine sequentielle Datenstruktur, die das Einfügen neuer Ele-
mente nur an ihrem Ende, und das Löschen von Elementen nur am Anfang erlaubt – eben ganz
so wie eine echte Warteschlange.
Warteschlangen werden üblicherweise zum differenzierten Abarbeiten zeitlich geordneter Ein-
gaben/Befehle eingesetzt.

373
Die C++-Standardbibliothek

Anwendung
Die Klasse queue implementiert keinen wirklich neuen Container. Statt dessen ver-
wendet sie eine protected-Instanz eines sequentiellen Containers und macht nur die-
jenigen Methoden dieser Containerklasse zugänglich (durch Definition eigener
public-Methoden, die lediglich die entsprechenden Methoden der Containerklasse
aufrufen), die für die Implementierung einer Warteschlange nötig sind.
Hinter queue steht ein Klassentemplate, aus dem man zuerst eine Container-Klasse
erzeugen muß. Dabei übergibt man dem ersten Template-Parameter T den Datentyp
der zu verwaltenden Objekte.
queue<int> container;
Zusätzlich kann man als zweiten Template-Parameter einen Container spezifizie-
ren, der intern zur Verwahrung der Elemente verwendet wird. Der übergebene
Container muß über die Methoden empty(), size(), front(), back(), push_back(),
pop_front() verfügen (wie beispielsweise list oder deque, aber nicht vector). Stan-
dardmäßig wird ein deque<T>-Container verwendet.
queue<int, list<int> > container;

Referenz
template <class T, class Container = deque<T> >
class queue {
public:
typedef typename Container::value_type value_type;
typedef typename Container::size_type size_type;
typedef typename Container container_type;
protected:
Container c;
public:
explicit queue(const Container& = Container());
bool empty() const { return [Link](); }
size_type size() const { return [Link](); }
value_type& front() { return [Link](); }
const value_type& front() const { return [Link](); }
value_type& back() { return [Link](); }
const value_type& back() const { return [Link](); }
void push(const value_type& x) { c.push_back(x); }
void pop() { c.pop_front(); }
};

374
set und multiset

set und multiset


Assoziativer Container (aus Header set)

Beschreibung
Die Klassen set und multiset sind praktisch identisch zu map und multimap, mit dem Unter-
schied, daß map (multimap) ihre Schlüssel einsetzen, um schnellen Zugriff auf Objekte eines
anderen Typs zu gewähren, wohingegen für set (multiset) die Werte (Objekte) selbst die
Schlüssel darstellen.
Für set und multiset gilt daher:
● value_type = key_type = Key.
● value_compare = key_compare = Vergl.
● Index-Operator [] ist nicht definiert.

Anwendung
Hinter set und multiset stehen Klassentemplates, aus denen man zuerst Container-
Klassen erzeugen muß. Dabei übergibt man dem Template-Parameter T den Daten-
typ der zu verwaltenden Objekte.
set<int> container;
Zusätzlich kann man als zweiten Template-Parameter ein Funktionsobjekt überge-
ben, das festlegt, wie die Elemente im Container sortiert werden soll.
set<int, greater<int> > container;

Referenz

set <set>
template <class Key, class Compare = less<Key>,
class Allocator = allocator<Key> >
class set {
public:
typedef Key key_type;
typedef Key value_type;
typedef Compare key_compare;
typedef Compare value_compare;
typedef Allocator allocator_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;

375
Die C++-Standardbibliothek

typedef std::reverse_iterator<iterator> reverse_iterator;


typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
// Konstruktoren und Zuweisung:
explicit set(const Compare& comp = Compare(), const Allocator& =
Allocator());
template <class InputIterator>
set(InputIterator first, InputIterator last,
const Compare& comp = Compare(), const Allocator& =
Allocator());
set(const set<Key,Compare,Allocator>& x);
~set();
set<Key,Compare,Allocator>&
operator=(const set<Key,Compare,Allocator>& x);
allocator_type get_allocator() const;
// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Größe:
bool empty() const;
size_type size() const;
size_type max_size() const;
// Einfügen und Löschen:
pair<iterator,bool> insert(const value_type& x);
iterator insert(iterator position, const value_type& x);
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
void erase(iterator position);
size_type erase(const key_type& x);
void erase(iterator first, iterator last);
void swap(set<Key,Compare,Allocator>&);
void clear();
// Sonstiges:
key_compare key_comp() const;
value_compare value_comp() const;
iterator find(const key_type& x) const;
size_type count(const key_type& x) const;
iterator lower_bound(const key_type& x) const;
iterator upper_bound(const key_type& x) const;
pair<iterator,iterator> equal_range(const key_type& x) const;
};

set <set>
template <class Key, class Compare = less<Key>,
class Allocator = allocator<Key> >

376
set und multiset

class multiset {
public:
typedef Key key_type;
typedef Key value_type;
typedef Compare key_compare;
typedef Compare value_compare;
typedef Allocator allocator_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
// Konstruktoren und Zuweisung:
explicit multiset(const Compare& comp = Compare(),
const Allocator& = Allocator());
template <class InputIterator>
multiset(InputIterator first, InputIterator last,
const Compare& comp = Compare(), const Allocator& =
Allocator());
multiset(const multiset<Key,Compare,Allocator>& x);
~multiset();
multiset<Key,Compare,Allocator>&
operator=(const multiset<Key,Compare,Allocator>& x);
allocator_type get_allocator() const;
// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Größe:
bool empty() const;
size_type size() const;
size_type max_size() const;
// Einfügen und Löschen:
iterator insert(const value_type& x);
iterator insert(iterator position, const value_type& x);
template <class InputIterator>
void insert(InputIterator first, InputIterator last);
void erase(iterator position);
size_type erase(const key_type& x);

377
Die C++-Standardbibliothek

void erase(iterator first, iterator last);


void swap(multiset<Key,Compare,Allocator>&);
void clear();
// Sonstiges:
key_compare key_comp() const;
value_compare value_comp() const;
iterator find(const key_type& x) const;
size_type count(const key_type& x) const;
iterator lower_bound(const key_type& x) const;
iterator upper_bound(const key_type& x) const;
pair<iterator,iterator> equal_range(const key_type& x) const;
};

stack
Sequentieller Container (aus Header stack)

Beschreibung
Ein Stack oder Keller ist eine sequentielle Datenstruktur, die Einfügen und Löschen nur an
ihrem Ende erlaubt.
Keller, Stapel oder Stack bezeichnen eine Datenstruktur, die Zugriffe nur auf ihrem Ende
erlaubt. Sie verhält sich also ähnlich wie ein Stapel Bücher, auf den sich weitere Bücher schich-
ten lassen und dessen oberstes Buch entfernt werden kann, während das Einschieben oder Ent-
fernen eines Buches in der Mitte des Stapels verboten ist. Für die Verarbeitung von Eingaben
bedeutet dies, daß die letzte Eingabe als erste abgearbeitet wird, also gerade umgekehrt wie
bei einer queue.

Anwendung
Die Klasse stack implementiert keinen wirklich neuen Container. Statt dessen ver-
wendet sie eine protected-Instanz eines sequentiellen Containers und macht nur die-
jenigen Methoden dieser Container-Klasse zugänglich (durch Definition eigener
public-Methoden, die lediglich die entsprechenden Methoden der Container-Klasse
aufrufen), die für die Implementierung eines Stacks nötig sind.
Hinter stack steht ein Klassentemplate, aus dem man zuerst eine Container-Klasse
erzeugen muß. Dabei übergibt man dem ersten Template-Parameter T den Datentyp
der zu verwaltenden Objekte.
stack<int> container;
Zusätzlich kann man als zweiten Template-Parameter einen Container spezifizie-
ren, der intern zur Verwahrung der Elemente verwendet wird. Der übergebene
Container muß über die Methoden empty(), size(), back(), push_back(),
pop_back() verfügen (wie beispielsweise list, vector oder deque). Standardmäßig
wird ein deque<T>-Container verwendet.

378
vector

stack<int, list<int> > container;

Referenz
template <class T, class Container = deque<T> >
class stack {
public:
typedef typename Container::value_type value_type;
typedef typename Container::size_type size_type;
typedef typename Container container_type;
protected:
Container c;
public:
explicit stack(const Container& = Container());
bool empty() const { return [Link](); }
size_type size() const { return [Link](); }
value_type& top() { return [Link](); }
const value_type& top() const { return [Link](); }
void push(const value_type& x) { c.push_back(x); }
void pop() { c.pop_back(); }
};

vector
Sequentieller Container (aus Header vector)

Beschreibung
Die Klasse vector bietet wie ein Array schnellen, direkten Zugriff auf einzelne Elemente ([]-
Operator, at()-Methode) sowie Einfügen und Löschen von Elementen an beliebigen Positionen
(letzteres allerdings nur in linearer Zeit, da diese Operationen mit dem internen Verschieben
der anderen Container-Elemente verbunden sind). Schneller, in konstanter Zeit, kann man nur
am Ende der Datenstruktur einfügen oder löschen.
Im Gegensatz zu deque ist vector also nur für das Einfügen und Löschen am Ende der Daten-
struktur optimiert. Dafür ist der Zugriff auf beliebige Positionen etwas schneller als bei deque.
Im Vergleich zu einem list-Container ist das Einfügen und Löschen an mittleren Positionen
zeitaufwendiger, dafür erlaubt vector den bequemen indizierten Zugriff auf bestimmte Positio-
nen (zum Lesen oder Schreiben).
Iteratoren für vector-Container sollten mindestens der forward_iterator-Kategorie angehö-
ren, verschiedene Funktionen verlangen aber höhere Iteratorenkategorien. Einfüge- und
Löschoperationen führen unter Umständen zur Ungültigkeit bestehender Iteratoren und Refe-
renzen auf Container-Elemente.

379
Die C++-Standardbibliothek

Anwendung
Hinter vector steht ein Klassentemplate, aus dem man zuerst eine Container-Klasse
erzeugt. Dabei übergibt man dem ersten Template-Parameter T den Datentyp der zu
verwaltenden Objekte.
vector<int> container;
Die überladenen Formen der Konstruktoren erlauben die Einrichtung leerer Contai-
ner oder Container, die mehrere Kopien eines Elements bzw. die Kopie einer
Sequenz von Elementen aus einem anderen Container enthalten.
Neue Elemente können mittels insert(), push_back(), resize() oder assign() einge-
fügt werden, wobei letztere Funktion den Container zuvor leert.
Bestehende Elemente können mittels erase(), pop_back(), resize() oder clear()
gelöscht werden.
Der Zugriff auf einzelne Elemente kann mit Hilfe zurückgelieferter Iteratoren
geschehen (begin(), end(), rbegin(), rend() sowie insert() ) oder über zurückge-
gebene Referenzen (Operator [], at(), front(), back() ).
Schließlich ist es möglich, über die globalen Funktionen der Header-Datei <algo-
rithm> Container zu manipulieren, zu sortieren, in ihnen zu suchen, etc.

Referenz
template <class T, class Allocator = allocator<T> >
class vector {
public:
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef implementation defined iterator;
typedef implementation defined const_iterator;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef T value_type;
typedef Allocator allocator_type;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator>
const_reverse_iterator;
// Konstruktoren und Zuweisung:
explicit vector(const Allocator& = Allocator());
explicit vector(size_type n, const T& value = T(),
const Allocator& = Allocator());
template <class InputIterator>
vector(InputIterator first, InputIterator last,
const Allocator& = Allocator());
vector(const vector<T,Allocator>& x);
~vector();

380
vector

vector<T,Allocator>& operator=(const vector<T,Allocator>& x);


template <class InputIterator>
void assign(InputIterator first, InputIterator last);
template <class Size, class U> void assign(Size n, const U& u = U());
allocator_type get_allocator() const;
// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Größe:
size_type size() const;
size_type max_size() const;
void resize(size_type sz, T c = T());
size_type capacity() const;
bool empty() const;
void reserve(size_type n);
// Zugriff auf Elemente:
reference operator[](size_type n);
const_reference operator[](size_type n) const;
const_reference at(size_type n) const;
reference at(size_type n);
reference front();
const_reference front() const;
reference back();
const_reference back() const;
// Einfügen und Löschen:
void push_back(const T& x);
void pop_back();
iterator insert(iterator position, const T& x = T());
void insert(iterator position, size_type n, const T& x);
template <class InputIterator>
void insert(iterator position, InputIterator first,
InputIterator last);
iterator erase(iterator position);
iterator erase(iterator first, iterator last);
void swap(vector<T,Allocator>&);
void clear();
};

381
Die C++-Standardbibliothek

Die Iteratoren-Klassen

Allgemeines
Beschreibung
Iteratoren sind Abstraktionen von Zeigern und dienen dazu, auf Elemente von Container
zugreifen zu können.

Anwendung
Iteratoren werden von den Algorithmen verwendet, um auf die Elemente aus den
verschiedensten Container zuzugreifen. Das Problem, das hierbei auftaucht und
weswegen die STL mit Iteratoren arbeitet, besteht darin, daß der Algorithmus mit
einer feststehenden Syntax über die Iteratoren auf die Elemente im Container
zugreifen und gegebenenfalls von Element zu Element springen möchte. Auf der
anderen Seite liegen den Containern unterschiedliche Datenstrukturen (dynamische
Arrays, Listen, Bäume, etc.) zugrunde, für die Operationen wie das Springen von
Element zu Element ganz unterschiedlich gelöst sind. Aus diesem Grunde imple-
mentieren die Container ihre Iteratoren selbst und halten sich dabei an die für Ite-
ratoren typische Schnittstelle, so daß diese von den Algorithmen verwendet werden
können.
Nach dem Leistungsumfang der Iteratoren unterscheidet man verschiedene Iterator-
Kategorien.

Die Iteratoren-Kategorien
Die Kategorie eines Iterators bestimmt seine Leistungsfähigkeit und damit sein Ein-
satzgebiet.

Kategorie output_iterator
Mit Output-Iteratoren kann man die Elemente eines Containers durchlaufen und
den Wert der Elemente verändern, nicht aber lesen. Außerdem können Sie sich mit
einem Input-Iterator von der Position seiner Initialisierung an nur in Richtung des
Container-Endes bewegen, d. h., Sie können einen Input-Iterator inkrementieren
(++), aber nicht dekrementieren (--).
Zum Einfügen neuer Werte in einen Container dienen spezielle Adaptionen – die
sogenannten Insert-Iteratoren, die Zuweisungen an das Element des Iterators in
eine Einfüge-Operation umsetzen.

382
Allgemeines

Anforderungen
● Kopierkonstruktor und Destruktor
● Zuweisung =
● Dereferenzierung zum Schreiben *i = t
● Inkrement ++i, i++

Kategorie input_iterator
Mit Input-Iteratoren kann man auf Container-Elemente zugreifen, um ihre Werte
auszulesen, aber man kann die Elemente nicht verändern. Außerdem können Sie
sich mit einem Input-Iterator von der Position seiner Initialisierung an nur in Rich-
tung des Container-Endes bewegen, d. h., Sie können einen Input-Iterator inkre-
mentieren (++), aber nicht dekrementieren (--).
Anforderungen an Iterator
● Kopierkonstruktor und Destruktor
● Zuweisung =
● Vergleich ==, wobei aus i == j auch *I == *j folgt (allerdings nicht ++i == ++j)
● Vergleich !=
● Dereferenzierung zum Lesen *i, j->m
● Inkrement ++i, i++

Kategorie forward_iterator
Forward-Iteratoren können zum Lesen und Schreiben verwendet werden. Mit For-
ward-Iteratoren kann man sich zwar auch nur mit Hilfe des Inkrement-Operators
in Richtung Container-Ende bewegen, doch kann man mit Kopien eines Forward-
Iterators einen Container mehrfach durchlaufen.
Anforderungen an Iterator (zusätzlich zu input_iterator)
● Konstruktor zum Erzeugen
● Dereferenzierung zum Schreiben: *i = t

Kategorie bidirectional_iterator
Bidirektionale Iteratoren verfügen über alle Eigenschaften von Forward-Iteratoren,
sowie die Möglichkeit, einen Container vorwärts wie rückwärts zu durchlaufen.
Anforderungen an Iterator (zusätzliche)
● Dekrement --i, i--
● *i--

383
Die C++-Standardbibliothek

Kategorie random_acces_iterator
Random Access-Iteratoren verfügen über alle Eigenschaften von Bidirectional-Itera-
toren, sowie Vergleichsoperationen und die Möglichkeit, auf Elemente direkt zuzu-
greifen, statt alle dazwischenliegenden Elemente zu durchlaufen.
Anforderungen an Iterator (zusätzliche)
● Vorwärtssprünge i += n, a + n
● Rückwärtssprünge i -= n, a- n
● Distanz i – j
● Indizierung i[n]
● Vergleiche i < j, i <= j, i > j, i >= j

reverse_iterator
aus <iterator>

Beschreibung
Eine Instanz der Klasse reverse_iterator ist eine Adaption eines bidirektionalen oder Random
Access-Iterators, mit dem man in umgekehrter Richtung durch einen Container laufen kann,
wobei gilt:
&*(reverse_iterator(i)) == &*(i-1)
Ein reverse_iterator ist somit ein Iterator, der eine Erhöhung in eine Verringerung und eine
Verringerung in eine Erhöhung umsetzt. So kann man eine Funktion, die einen Iterator von
vorne nach hinten durch eine Folge von Elementen laufen läßt, die Folge durch Übergabe eines
umkehrenden Iterators auch in umgekehrter Reihenfolge durchlaufen lassen.

Anwendung
Umkehrende Iteratoren kann man sich beispielsweise von den Container-Methoden
rbegin() und rend() zurückliefern lassen.
// Elemente eines Containers rueckwaerts ausgeben
typedef vector<int>::reverse_iterator r_iter;
for(r_iter i = [Link](); i != [Link](); i++)
cout << *i << endl;

384
Insert-Iteratoren

Referenz
template <class Iterator>
class reverse_iterator :
public iterator<iterator_traits<Iterator>::iterator_category,
iterator_traits<Iterator>::value_type,
iterator_traits<Iterator>::difference_type,
iterator_traits<Iterator>::pointer,
iterator_traits<Iterator>::reference> {
protected:
Iterator current;
public:
typedef Iterator iterator_type;
reverse_iterator();
explicit reverse_iterator(Iterator x);
Iterator base() const;
Reference operator*() const;
Pointer operator->() const;
reverse_iterator& operator++();
reverse_iterator operator++(int);
reverse_iterator& operator--();
reverse_iterator operator--(int);
reverse_iterator operator+ (Distance n) const;
reverse_iterator& operator+=(Distance n);
reverse_iterator operator- (Distance n) const;
reverse_iterator& operator-=(Distance n);
Reference operator[](Distance n) const;
};

Insert-Iteratoren
Beschreibung
Insert-Iteratoren sind Iteratoren-Adapter, die eine Kopiersyntax (Überschreiben) in eine Einfü-
geoperation umwandeln.

Anwendung
Auf diese Weise kann man Algorithmen, die Elemente mit Hilfe von Iteratoren
kopieren, durch Übergabe von Insert-Iteratoren auch zum Einfügen verwenden.
Insert-Iteratoren läßt man sich meist von einer der zugehörigen Funktionentempla-
tes back_inserter(), front_inserter(), inserter() (siehe unten) zurückliefern, denen
man bei der Instanziierung die Container-Klasse, auf der der Iterator operieren soll,
als Template-Parameter übergibt.
Die Iteratoren selbst verwenden eine Referenz auf den assoziierten Container und
Operatoren zum Durchlaufen und Einfügen in den Container.

385
Die C++-Standardbibliothek

Beispiel
copy([Link](), [Link](),
back_inserter(container));
oder auch
back_insert_iterator<vector<int> > b_iter(container);
b_iter = 333; // Ans Container-Ende anhaengen

back_insert_iterator <iterator>
Der Iterator wird direkt für einen Container erzeugt und ermöglicht das komforta-
ble Einfügen von Elementen am Ende des Containers.
Die Implementierung von back_insert_iterator benutzt zum Einfügen die push_back-
Methode des Containers. Folglich kann ein back_insert-Iterator nur auf Container
angewendet werden, für die diese Methode definiert ist (vector, deque, list).
template <class Container>
class back_insert_iterator :
public iterator<output_iterator_tag,void,void,void,void> {
protected:
Container& container;
public:
typedef Container container_type;
explicit back_insert_iterator(Container& x);
back_insert_iterator<Container>&
operator=(const typename Container::value_type& value);
back_insert_iterator<Container>& operator*();
back_insert_iterator<Container>& operator++();
back_insert_iterator<Container> operator++(int);
};
template <class Container>
back_insert_iterator<Container> back_inserter(Container& x);

front_insert_iterator <iterator>
Der Iterator wird direkt für einen Container erzeugt und ermöglicht das komforta-
ble Einfügen von Elementen am Anfang des Containers.
Die Implementierung von front_insert_iterator benutzt zum Einfügen die
push_front-Methode des Containers. Folglich kann ein front_insert-Iterator nur auf
Container angewendet werden, für die diese Methode definiert ist (deque, list).
template <class Container>
class front_insert_iterator :
public iterator<output_iterator_tag,void,void,void,void> {
protected:
Container& container;
public:
typedef Container container_type;
explicit front_insert_iterator(Container& x);

386
Stream-Iteratoren

front_insert_iterator<Container>&
operator=(const typename Container::value_type& value);
front_insert_iterator<Container>& operator*();
front_insert_iterator<Container>& operator++();
front_insert_iterator<Container> operator++(int);
};
template <class Container>
front_insert_iterator<Container> front_inserter(Container& x);

insert_iterator <iterator>
Der Iterator wird direkt für einen Container erzeugt und ermöglicht das komforta-
ble Einfügen von Elementen am Anfang des Containers.
template <class Container>
class insert_iterator :
public iterator<output_iterator_tag,void,void,void,void> {
protected:
Container& container;
typename Container::iterator iter;
public:
typedef Container container_type;
insert_iterator(Container& x, typename Container::iterator i);
insert_iterator<Container>&
operator=(const typename Container::value_type& value);
insert_iterator<Container>& operator*();
insert_iterator<Container>& operator++();
insert_iterator<Container>& operator++(int);
};
template <class Container, class Iterator>
insert_iterator<Container> inserter(Container& x, Iterator i);

Stream-Iteratoren
Beschreibung
Stream-Iteratoren sind Adapter, mit deren Hilfe man auf Iteratoren beruhende Algorithmen
(allgemeiner Funktionen) zum Einlesen aus oder Schreiben in Dateien nutzen kann. Die »Con-
tainer-Elemente«, auf die der Iterator zugreift, sind dann die Ein- und Ausgaben.

Anwendung
Bei der Instanziierung des Iterators aus seinem Klassentemplate wird als Template-
Parameter der Datentyp der »Container-Elemente« übergeben. Den Stream, auf
dem operiert wird, kann man dem Konstruktor übergeben.

387
Die C++-Standardbibliothek

Beispiel
// Über istream_iterator Container-Elemente einlesen
copy(istream_iterator<int>(cin), istream_iterator<int>(),
back_inserter(container));
ostream_iterator<int, char> (cout,"\n"));
// Über ostream_iterator Container-Elemente ausgeben
copy([Link](), [Link](),
ostream_iterator<int, char> (cout,"\n"));

istream_iterator <iterator>
Der Iterator ist zum Lesen von Daten aus einem Stream konzipiert. Da er von der
Klasse input_iterator abgeleitet ist, ist er nur für einmalige Durchläufe zu gebrau-
chen.
Die Tatsache, daß es sich um einen Input-Iterator und keinen Forward-Iterator
handelt (letzterer würde mehrfache Durchläufe erlauben), sollte seinen Nutzen
nicht einschränken, da die eingelesenen Daten üblicherweise im Arbeitsspeicher
gepuffert werden, wo entsprechende Operationen wesentlich schneller ausgeführt
werden können.

Es ist nicht möglich, einem istream_iterator Daten zuzuweisen.


template <class T, class charT, class traits = char_traits<charT>,
class Distance = ptrdiff_t>
class istream_iterator
: public iterator<input_iterator_tag,T,Distance,const T*, const T&> {
public:
typedef charT char_type
typedef traits traits_type;
typedef basic_istream<charT,traits> istream_type;
istream_iterator();
istream_iterator(istream_type& s);
istream_iterator(const istream_iterator<T,charT,traits,Distance>& x);
~istream_iterator();
const T& operator*() const;
const T* operator->() const;
istream_iterator<T,charT,traits,Distance>& operator++();
istream_iterator<T,charT,traits,Distance> operator++(int);
};

ostream_iterator <iterator>
Der Iterator ist zur Ausgabe von Daten in einen Stream konzipiert. Da er von der
Klasse output_iterator abgeleitet ist, ist er nur für einmalige Durchläufe zu gebrau-
chen.
Die Tatsache, daß es sich um einen Output-Iterator und keinen Forward-Iterator
handelt (letzterer würde mehrfache Durchläufe erlauben), sollte seinen Nutzen

388
Stream-Iteratoren

nicht einschränken, da die geschriebenen Daten üblicherweise im Arbeitsspeicher


gepuffert werden, wo entsprechende Operationen wesentlich schneller ausgeführt
werden können.
Es ist nicht möglich, den Wert eines ostream_iterators abzufragen.
Der Dereferenzierungsoperator darf nur auf der linken Seite von Zuweisungen stehen.
template <class T, class charT, class traits = char_traits<charT> >
class ostream_iterator
: public iterator<output_iterator_tag,void,void,void,void> {
public:
typedef charT char_type;
typedef traits traits_type;
typedef basic_ostream<charT,traits> ostream_type;
ostream_iterator(ostream_type& s);
ostream_iterator(ostream_type& s, const charT* delimiter);
ostream_iterator(const ostream_iterator<T,charT,traits>& x);
~ostream_iterator();
ostream_iterator<T,charT,traits>& operator=(const T& value);
ostream_iterator<T,charT,traits>& operator*();
ostream_iterator<T,charT,traits>& operator++();
ostream_iterator<T,charT,traits>& operator++(int);
};

istreambuf_iterator <iterator>
Der Iterator ist zum Lesen von Zeichen aus einem basic_streambuf-Objekt konzi-
piert. Der Iterator ist nur für einmalige Durchläufe zu gebrauchen.
template<class charT, class traits = char_traits<charT> >
class istreambuf_iterator
: public iterator<input_iterator_tag, charT,
typename traits::off_type, charT*, charT&> {
public:
typedef charT char_type;
typedef traits traits_type;
typedef typename traits::int_type int_type;
typedef basic_streambuf<charT,traits> streambuf_type;
typedef basic_istream<charT,traits> istream_type;

istreambuf_iterator() throw();
istreambuf_iterator(istream_type& s) throw();
istreambuf_iterator(streambuf_type* s) throw();
istreambuf_iterator(const proxy& p) throw();
charT operator*() const;
istreambuf_iterator<charT,traits>& operator++();
proxy operator++(int);
bool equal(istreambuf_iterator& b);
};

389
Die C++-Standardbibliothek

ostreambuf_iterator <iterator>
Der Iterator ist zum Schreiben von Zeichen in ein basic_streambuf-Objekt konzi-
piert. Der Iterator ist nur für einmalige Durchläufe zu gebrauchen.
Der Dereferenzierungsoperator darf nur auf der linken Seite von Zuweisungen ste-
hen.
template <class charT, class traits = char_traits<charT> >
class ostreambuf_iterator :
iterator<output_iterator_tag,void,void,void,void>{
public:
typedef charT char_type;
typedef traits traits_type;
typedef basic_streambuf<charT,traits> streambuf_type;
typedef basic_ostream<charT,traits> ostream_type;
public:
ostreambuf_iterator(ostream_type& s) throw();
ostreambuf_iterator(streambuf_type* s) throw();
ostreambuf_iterator& operator=(charT c);
ostreambuf_iterator& operator*();
ostreambuf_iterator& operator++();
ostreambuf_iterator& operator++(int);
bool failed() const throw();
};

Unterstützung eigener Implementierungen


Um Funktionen per Parameter an die unterschiedlichen Iterator-Kategorien anpas-
sen zu können, definiert die C++-Bibliothek die folgenden Strukturen.

struct iterator_traits <iterator>


template<class Iterator> struct iterator_traits {
typedef Iterator::difference_type difference_type;
typedef Iterator::value_type value_type;
typedef Iterator::pointer pointer;
typedef Iterator::reference reference;
typedef Iterator::iterator_category iterator_category;
};
die auch als Spezialisierung für normale Zeiger vorliegt
template<class T> struct iterator_traits<T*> {
typedef ptrdiff_t difference_type; typedef T value_type;
typedef T* pointer; typedef T& reference;
typedef random_access_iterator_tag iterator_category;
};

390
Unterstützung eigener Implementierungen

Iterator-Tags <iterator>
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag: public input_iterator_tag {};
struct bidirectional_iterator_tag: public forward_iterator_tag {};
struct random_access_iterator_tag: public bidirectional_iterator_tag {};
Diese Strukturen dienen dazu, als Funktions- oder Template-Parameter die Anpas-
sung an die verschiedenen Iterator-Kategorien zu ermöglichen.

Beispiel
Das folgende Beispiel enthält zwei Funktionen für bidirektionale und Random
Access-Iteratoren und eine Kapselfunktion, die je nach übergebenem Iterator-Typ
die am besten passende Implementierung aufruft:
template <class mindestensBDIter>
inline void tu_was(mindestensBDIter first, mindestensBDIter last) {
tu_was(first, last,
iterator_traits<mindestensBDIter>::iterator_category());
}

template <class BDIter>


void tu_was(BDIter first, BDIter last,
bidirectional_iterator_tag)
{ // allgemein, aber wenig effizient }
template <class RAIter>
void tu_was(RAIter first, RAIter last,
random_access_iterator_tag) {
{ // effizient, aber weniger allgemein }

struct iterator <iterator>


Eigene Iteratoren können von der Klasse iterator abgeleitet werden:
template<class Category, class T, class Distance = ptrdiff_t,
class Pointer = T*, class Reference = T&>
struct iterator {
typedef T value_type;
typedef Distance difference_type;
typedef Pointer pointer;
typedef Reference reference;
typedef Category iterator_category;
}
Schließlich gibt es zwei Hilfsfunktionen, mit denen man Iteratoren beliebiger Kate-
gorie um n Positionen verrücken oder den Abstand zwischen zwei Iteratoren ermit-
teln kann:

391
Die C++-Standardbibliothek

advance() <iterator>
template <class InIter, class Distance>
void advance(InIter& i, Distance n);
Verschiebt den Iterator um n Positionen (mittels +/- oder ++/--)

distance() <iterator>
template <class InIter>
iterator_traits<InIter>::difference_type distance(InIter& i,InIter& j);
Liefert die Distanz (Anzahl Inkrement/Dekrementoperationen) zwischen i und j.

Die Algorithmen
Beschreibung
Die Algorithmen sind eine Sammlung von Funktionentemplates, die für beliebige Datentypen
spezialisiert und per Iteratoren auf die Objekte von Containern angewendet werden können.

Anwendung
Da die Algorithmen nicht als Methoden der Container-Templates, sondern als
eigenständige Templates implementiert sind, erfolgt die Verbindung zu den Elemen-
ten im Container über Iteratoren. Dies hat beispielsweise den Vorteil, daß die Algo-
rithmen nicht für jeden Container einzeln implementiert werden müssen und auch
auf selbst definierte Container (inklusive Arrays und dynamische Felder) angewen-
det werden können.
Voraussetzung ist allerdings, daß die Schnittstelle zwischen Algorithmus und Con-
tainer stimmt. Die Schnittstelle sind die Iteratoren. In der folgenden Aufzählung
können Sie daher an den Namen der Iterator-Template-Parameter ablesen, welchen
Anforderungen der Iterator, der dem Algorithmus übergeben wird, genügen muß.
Wenn die Schnittstelle stimmt, ist die Anwendung der Algorithmen auf Container-
Elemente ganz einfach:
deque<int> container(5);
...
fill([Link](), [Link](), 4);
oder
int feld[30];
...
fill(&feld[0], &feld[30], 3);

392
Unterstützung eigener Implementierungen

Etliche der Algorithmen benötigen zur Ausführung ihrer Operation noch ein weite-
res Argument, üblicherweise:
● einen Wert (beispielsweise fill(), das den Elementen den übergebenen Wert
zuweist)
● oder ein Funktionsobjekt, das meist eine Bedingung spezifiziert, die erfüllt sein
muß, damit die Operation des Algorithmus auf ein Element angewendet wird
(z. B. make_heap() wandelt einen Bereich in einen Heap um. Durch Übergabe ei-
nes Funktionsobjekts kann man eine Vergleichsfunktion übergeben, die die
Sortierung des Heaps festlegt.)
Funktionsobjekte, die Vergleiche durchführen, werden in der nachfolgenden
Auflistung der Algorithmen als Compare bezeichnet, Funktionsobjekte, die auf
einen oder zwei dereferenzierte Iteratoren angewendet und dann einen bool-
Wert zurückliefern, werden als Predicate oder BinaryPredicate bezeichnet.
Oft sind die Templates der Algorithmen überladen, so daß ein und derselbe Algo-
rithmus mit verschiedenen Argumenten aufgerufen werden kann. So kann der
Algorithmus find() nach einem Element suchen, das entweder einen bestimmten
Wert enthält oder eine bestimmte Bedingung erfüllt.
Aus numeric:
template <class InputIter, class T>
accumulate(InputIter first, InputIter last, T init);
template <class InputIter, class T, class BinaryOperation>
accumulate(InputIter first, InputIter last, T init,
BinaryOperation binary_op);
template <class InputIter, class OutputIter>
OutputIter adjacent_difference(InputIter first, InputIter last,
OutputIter result);
template <class InputIter, class OutputIter, class BinaryOperation>
OutputIter adjacent_difference(InputIter first, InputIter last,
OutputIter result,
BinaryOperation binary_op);
template <class InputIter1, class InputIter2, class T>
T inner_product(InputIter1 first1, InputIter1 last1,
InputIter2 first2, T init);
template <class InputIter1, class InputIter2, class T,
class BinaryOperation1, class BinaryOperation2>
T inner_product(InputIter1 first1, InputIter1 last1,
InputIter2 first2, T init,
BinaryOperation1 binary_op1, BinaryOperation2 binary_op2);
template <class InputIter, class OutputIter>
OutputIter partial_sum(InputIter first, InputIter last,
OutputIter result);
template <class InputIter, class OutputIter, class BinaryOperation>
OutputIter partial_sum(InputIter first, InputIter last,
OutputIter result, BinaryOperation binary_op);
Aus algorithm:

393
Die C++-Standardbibliothek

template<class ForwardIter>
ForwardIter adjacent_find(ForwardIter first, ForwardIter last);
template<class ForwardIter, class BinaryPredicate>
ForwardIter adjacent_find(ForwardIter first, ForwardIter last,
BinaryPredicate pred);
template<class ForwardIter, class T>
bool binary_search(ForwardIter first,ForwardIter last,const T& value);
template<class ForwardIter, class T, class Compare>
bool binary_search(ForwardIter first, ForwardIter last,
const T& value, Compare comp);
template<class InputIter, class T>
Iter_traits<InputIter>::difference_type
count(InputIter first, InputIter last, const T& value);
template<class InputIter, class Predicate>
Iter_traits<InputIter>::difference_type
count_if(InputIter first, InputIter last, Predicate pred);
template<class InputIter, class OutputIter>
OutputIter copy(InputIter first, InputIter last, OutputIter result);
template<class BidirectionalIter1, class BidirectionalIter2>
BidirectionalIter2 copy_backward(BidirectionalIter1 first,
BidirectionalIter1 last,
BidirectionalIter2 result);
template<class InputIter1, class InputIter2>
bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2);
template<class InputIter1, class InputIter2, class BinaryPredicate>
bool equal(InputIter1 first1, InputIter1 last1,
InputIter2 first2, BinaryPredicate pred);
template<class ForwardIter, class T>
pair<ForwardIter, ForwardIter>
equal_range(ForwardIter first, ForwardIter last, const T& value);
template<class ForwardIter, class T, class Compare>
pair<ForwardIter, ForwardIter>
equal_range(ForwardIter first, ForwardIter last, const T& value,
Compare comp);
template<class ForwardIter, class T>
void fill(ForwardIter first, ForwardIter last, const T& value);
template<class OutputIter, class Size, class T>
void fill_n(OutputIter first, Size n, const T& value);
template<class InputIter, class T>
InputIter find(InputIter first, InputIter last, const T& value);
template<class ForwardIter1, class ForwardIter2>
ForwardIter1 find_end(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2);
template<class ForwardIter1, class ForwardIter2, class BinaryPredicate>
ForwardIter1 find_end(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2,
BinaryPredicate pred);
template<class ForwardIter1, class ForwardIter2>
ForwardIter1 find_first_of(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2);

394
Unterstützung eigener Implementierungen

template<class ForwardIter1, class ForwardIter2, class BinaryPredicate>


ForwardIter1 find_first_of(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2,
BinaryPredicate pred);
template<class InputIter, class Predicate>
InputIter find_if(InputIter first, InputIter last, Predicate pred);
template<class InputIter, class Function>
Function for_each(InputIter first, InputIter last, Function f);
template<class ForwardIter, class Generator>
void generate(ForwardIter first, ForwardIter last, Generator gen);
template<class OutputIter, class Size, class Generator>
void generate_n(OutputIter first, Size n, Generator gen);
template<class InputIter1, class InputIter2>
bool includes(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2);
template<class InputIter1, class InputIter2, class Compare>
bool includes(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2, Compare comp);
template<class BidirectionalIter>
void inplace_merge(BidirectionalIter first,
BidirectionalIter middle,
BidirectionalIter last);
template<class BidirectionalIter, class Compare>
void inplace_merge(BidirectionalIter first,
BidirectionalIter middle,
BidirectionalIter last, Compare comp);
template<class ForwardIter1, class ForwardIter2>
void iter_swap(ForwardIter1 a, ForwardIter2 b);
template<class InputIter1, class InputIter2>
bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2);
template<class InputIter1, class InputIter2, class Compare>
bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
Compare comp);
template<class ForwardIter, class T>
ForwardIter lower_bound(ForwardIter first, ForwardIter last,
const T& value);
template<class ForwardIter, class T, class Compare>
ForwardIter lower_bound(ForwardIter first, ForwardIter last,
const T& value, Compare comp);
template<class RandomAccessIter>
void make_heap(RandomAccessIter first, RandomAccessIter last);
template<class RandomAccessIter, class Compare>
void make_heap(RandomAccessIter first, RandomAccessIter last,
Compare comp);
template<class T> const T& max(const T& a, const T& b);
template<class T, class Compare>
const T& max(const T& a, const T& b, Compare comp);
template<class ForwardIter>
ForwardIter max_element(ForwardIter first, ForwardIter last);

395
Die C++-Standardbibliothek

template<class ForwardIter, class Compare>


ForwardIter max_element(ForwardIter first, ForwardIter last,
Compare comp);
template<class InputIter1, class InputIter2, class OutputIter>
OutputIter merge(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
OutputIter result);
template<class InputIter1, class InputIter2, class OutputIter,
class Compare>
OutputIter merge(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
OutputIter result, Compare comp);
template<class T> const T& min(const T& a, const T& b);
template<class T, class Compare>
const T& min(const T& a, const T& b, Compare comp);
template<class ForwardIter>
ForwardIter min_element(ForwardIter first, ForwardIter last);
template<class ForwardIter, class Compare>
ForwardIter min_element(ForwardIter first, ForwardIter last,
Compare comp);
template<class InputIter1, class InputIter2>
pair<InputIter1, InputIter2>
mismatch(InputIter1 first1, InputIter1 last1, InputIter2 first2);
template<class InputIter1, class InputIter2, class BinaryPredicate>
pair<InputIter1, InputIter2>
mismatch(InputIter1 first1, InputIter1 last1,
InputIter2 first2, BinaryPredicate pred);
template<class BidirectionalIter>
bool next_permutation(BidirectionalIter first,
BidirectionalIter last);
template<class BidirectionalIter, class Compare>
bool next_permutation(BidirectionalIter first,
BidirectionalIter last, Compare comp);
template<class RandomAccessIter>
void nth_element(RandomAccessIter first, RandomAccessIter nth,
RandomAccessIter last);
template<class RandomAccessIter, class Compare>
void nth_element(RandomAccessIter first, RandomAccessIter nth,
RandomAccessIter last, Compare comp);
template<class RandomAccessIter>
void partial_sort(RandomAccessIter first, RandomAccessIter middle,
RandomAccessIter last);
template<class RandomAccessIter, class Compare>
void partial_sort(RandomAccessIter first, RandomAccessIter middle,
RandomAccessIter last, Compare comp);
template<class InputIter, class RandomAccessIter>
RandomAccessIter
partial_sort_copy(InputIter first, InputIter last,
RandomAccessIter result_first,
RandomAccessIter result_last);
template<class InputIter, class RandomAccessIter, class Compare>

396
Unterstützung eigener Implementierungen

RandomAccessIter
partial_sort_copy(InputIter first, InputIter last,
RandomAccessIter result_first,
RandomAccessIter result_last,
Compare comp);
template<class BidirectionalIter, class Predicate>
BidirectionalIter partition(BidirectionalIter first,
BidirectionalIter last, Predicate pred);
template<class RandomAccessIter>
void pop_heap(RandomAccessIter first, RandomAccessIter last);
template<class RandomAccessIter, class Compare>
void pop_heap(RandomAccessIter first, RandomAccessIter last,
Compare comp);
template<class BidirectionalIter>
bool prev_permutation(BidirectionalIter first,
BidirectionalIter last);
template<class BidirectionalIter, class Compare>
bool prev_permutation(BidirectionalIter first,
BidirectionalIter last, Compare comp);
template<class RandomAccessIter>
void push_heap(RandomAccessIter first, RandomAccessIter last);
template<class RandomAccessIter, class Compare>
void push_heap(RandomAccessIter first, RandomAccessIter last,
Compare comp);
template<class RandomAccessIter>
void random_shuffle(RandomAccessIter first, RandomAccessIter last);
template<class RandomAccessIter, class RandomNumberGenerator>
void random_shuffle(RandomAccessIter first, RandomAccessIter last,
RandomNumberGenerator& rand);
template<class ForwardIter, class T>
ForwardIter remove(ForwardIter first, ForwardIter last,const T& value);
template<class InputIter, class OutputIter, class T>
OutputIter remove_copy(InputIter first, InputIter last,
OutputIter result, const T& value);
template<class InputIter, class OutputIter, class Predicate>
OutputIter remove_copy_if(InputIter first, InputIter last,
OutputIter result, Predicate pred);
template<class ForwardIter, class Predicate>
ForwardIter remove_if(ForwardIter first, ForwardIter last,
Predicate pred);
template<class ForwardIter, class T>
void replace(ForwardIter first, ForwardIter last,
const T& old_value, const T& new_value);
template<class InputIter, class OutputIter, class T>
OutputIter replace_copy(InputIter first, InputIter last,
OutputIter result,
const T& old_value, const T& new_value);
template<class Iter, class OutputIter, class Predicate, class T>
OutputIter replace_copy_if(Iter first, Iter last,
OutputIter result,
Predicate pred, const T& new_value);

397
Die C++-Standardbibliothek

template<class ForwardIter, class Predicate, class T>


void replace_if(ForwardIter first, ForwardIter last,
Predicate pred, const T& new_value);
template<class BidirectionalIter>
void reverse(BidirectionalIter first, BidirectionalIter last);
template<class BidirectionalIter, class OutputIter>
OutputIter reverse_copy(BidirectionalIter first,
BidirectionalIter last, OutputIter result);
template<class ForwardIter>
void rotate(ForwardIter first, ForwardIter middle, ForwardIter last);
template<class ForwardIter, class OutputIter>
OutputIter rotate_copy(ForwardIter first, ForwardIter middle,
ForwardIter last, OutputIter result);
template<class ForwardIter1, class ForwardIter2>
ForwardIter1 search(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2);
template<class ForwardIter1, class ForwardIter2, class BinaryPredicate>
ForwardIter1 search(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2, ForwardIter2 last2,
BinaryPredicate pred);
template<class ForwardIter, class Size, class T>
ForwardIter search_n(ForwardIter first, ForwardIter last,
Size count, const T& value);
template<class ForwardIter, class Size, class T, class BinaryPredicate>
ForwardIter1 search_n(ForwardIter first, ForwardIter last, Size count,
const T& value, BinaryPredicate pred);
template<class InputIter1, class InputIter2, class OutputIter>
OutputIter set_difference(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
OutputIter result);
template<class InputIter1, class InputIter2, class OutputIter,
class Compare>
OutputIter set_difference(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
OutputIter result, Compare comp);
template<class InputIter1, class InputIter2, class OutputIter>
OutputIter set_intersection(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
OutputIter result);
template<class InputIter1, class InputIter2, class OutputIter,
class Compare>
OutputIter set_intersection(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
OutputIter result, Compare comp);
template<class InputIter1, class InputIter2, class OutputIter>
OutputIter set_symmetric_difference(InputIter1 first1,InputIter1 last1,
InputIter2 first2,InputIter2 last2,
OutputIter result);
template<class InputIter1, class InputIter2, class OutputIter,
class Compare>
OutputIter set_symmetric_difference(InputIter1 first1,InputIter1 last1,

398
Unterstützung eigener Implementierungen

InputIter2 first2,InputIter2 last2,


OutputIter result, Compare comp);
template<class InputIter1, class InputIter2, class OutputIter>
OutputIter set_union(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
OutputIter result);
template<class InputIter1, class InputIter2, class OutputIter,
class Compare>
OutputIter set_union(InputIter1 first1, InputIter1 last1,
InputIter2 first2, InputIter2 last2,
OutputIter result, Compare comp);
template<class RandomAccessIter>
void sort(RandomAccessIter first, RandomAccessIter last);
template<class RandomAccessIter, class Compare>
void sort(RandomAccessIter first, RandomAccessIter last, Compare comp);
template<class BidirectionalIter, class Predicate>
BidirectionalIter stable_partition(BidirectionalIter first,
BidirectionalIter last,
Predicate pred);
template<class RandomAccessIter>
void stable_sort(RandomAccessIter first, RandomAccessIter last);
template<class RandomAccessIter, class Compare>
void stable_sort(RandomAccessIter first, RandomAccessIter last,
Compare comp);
template<class T> void swap(T& a, T& b);
template<class ForwardIter1, class ForwardIter2>
ForwardIter2 swap_ranges(ForwardIter1 first1, ForwardIter1 last1,
ForwardIter2 first2);
template<class InputIter, class OutputIter, class UnaryOperation>
OutputIter transform(InputIter first, InputIter last,
OutputIter result, UnaryOperation op);
template<class InputIter1, class InputIter2, class OutputIter,
class BinaryOperation>
OutputIter transform(InputIter1 first1, InputIter1 last1,
InputIter2 first2, OutputIter result,
BinaryOperation binary_op);
template<class ForwardIter>
ForwardIter unique(ForwardIter first, ForwardIter last);
template<class ForwardIter, class BinaryPredicate>
ForwardIter unique(ForwardIter first, ForwardIter last,
BinaryPredicate pred);
template<class InputIter, class OutputIter>
OutputIter unique_copy(InputIter first, InputIter last,
OutputIter result);
template<class InputIter, class OutputIter, class BinaryPredicate>
OutputIter unique_copy(InputIter first, InputIter last,
OutputIter result, BinaryPredicate pred);
template<class ForwardIter, class T>
ForwardIter upper_bound(ForwardIter first, ForwardIter last,
const T& value);
template<class ForwardIter, class T, class Compare>

399
Die C++-Standardbibliothek

ForwardIter upper_bound(ForwardIter first, ForwardIter last,


const T& value, Compare comp);
template<class RandomAccessIter>
void sort_heap(RandomAccessIter first, RandomAccessIter last);
template<class RandomAccessIter, class Compare>
void sort_heap(RandomAccessIter first, RandomAccessIter last,
Compare comp);

Die Stream-Klassen

Übersicht
Beschreibung
Die Stream-Klassen stellen die objektorientierte Alternative zu den ANSI C-Funktionen aus
stdio.h dar. Einen Stream kann man sich dabei als Datenfluß zwischen einer Quelle und einem
Ziel vorstellen, wobei je nach verwendeter Stream-Klasse die Instanz der Stream-Klasse entwe-
der die Quelle oder das Ziel ist. Für eine Instanz der Klasse ifstream ist die mit der Instanz ver-
bundene Datei die Quelle, für eine Instanz der Klasse ofstream wäre sie das Ziel.
Das Grundgerüst der C++-Stream-Klassen sieht nach dem neuen ANSI-Standard wie folgt aus:

ios_base

basic_ios
<class char T, class traits>

basic_istream
basic_ostream basic_ostream
<class char T, class traits> <class char T, class traits>

400
Übersicht

Eigenschaft Beschreibung
ios_base Die Klasse ios_base enthält Informationen sowie Typ- und Konstan-
tendefinitionen, die von allen Stream-Klassen verwendet werden und
nicht von einem speziellen Zeichentyp abhängen – beispielsweise die
Format-Flags, die Status-Bits, die Öffnungsmodi für Dateien.
(Viele Elemente, die mittlerweile in ios_base definiert sind, standen
früher in ios.)
basic_ios Die grundlegende Basisklasse. Sie ist als Template definiert, um
zeichentypspezifische Spezialisierungen zu erlauben. Als Template-
Argumente erwartet sie den Namen des Zeichentyps und eine
char_traits<charT>-Spezialisierung, die den Zeichentyp charakteri-
siert.
basic_ios stellt durch die Definition entsprechender Methoden und
Konstruktoren die Verbindung zu einem Pufferobjekt (für die
Zwischenspeicherung von Ein- und Ausgaben) und einem Locale-
Objekt (zur Anpassung an nationale Formate) her.
basic_istream und Abgeleitete Klassentemplates, die basic_ios als virtuelle Basis erben.
basic_ostream Die Klassen istream und ostream, die man zur Einrichtung von Ein-
und Ausgabe-Streams instanziieren kann, sind Spezialisierungen
dieser Klassentemplates für den Datentyp char. Die im vorangehen-
den Abschnitt vorgestellten Stream-Objekte cin, cout, cerr, clog
sind beispielsweise Instanzen der Klassen istream und ostream.
Die Klassentemplates istream und ostream dienen selbst wieder
anderen Stream-Klassen-Templates als Basisklassen.

Welche weiteren Hilfsklassen und abgeleiteten Klassen von diesem Grundgerüst


abhängen, sehen Sie in der folgenden Abbildung.

Anwendung
Um mit Streams arbeiten zu können, braucht man Stream-Objekte. Stream-Objekte
erzeugt man, indem man

401
Die C++-Standardbibliothek

● von den Klassentemplates der C++-Laufzeitbibliothek durch Spezialisierung


auf einen Zeichentyp Stream-Klassen erzeugt.
In der C++-Laufzeitbibliothek sind bereits etliche Stream-Klassen vordefiniert, bei-
spielsweise
typedef basic_istream<char> istream; // Eingabe-Stream-Klasse
typedef basic_ostream<char> ostream; // Ausgabe-Stream-Klasse
typedef basic_fstream<char> fstream; // DateiStream-Klasse
typedef basic_stringstream<char> stringstream; // Stringstream-Klasse
// für eine vollständige Liste schlagen Sie unter der Header-Datei iosfwd
// nach
● von den Stream-Klassen Stream-Objekte instanziiert.
In der Header-Datei iostream sind bereits folgende Stream-Objekte vordefiniert:
istream cin // StandardEingabe-Stream für char
ostream cout // StandardAusgabe-Stream für char
ostream cerr // Standardfehlerausgabe für char
ostream clog // Standardprotokollausgabe für char
wistream wcin // StandardEingabe-Stream für wchar_t
wostream wcout // StandardAusgabe-Stream für wchar_t
wostream wcerr // Standardfehlerausgabe für wchar_t
wostream wclog // Standardprotokollausgabe für wchar_t
Für die weitere Programmierung mit den Streams nutzt man
● die Methoden der Stream-Klassentemplates
● die überladenen Operatoren
● die Manipulatoren

Verweise
Siehe Kategorie Ein- und Ausgabe

ios_base
aus <ios>

Beschreibung
Die Klasse ios_base ist die Basisklasse zu basic_ios. Sie enthält keine Routinen zur Ein- und
Ausgabe, sondern umfaßt eine Reihe von Datentypen, Konstanten und Methoden zur Excep-
tion-Behandlung, zur Abfrage des Stream-Status und zur Formatierung der Ein- und Ausgabe.

402
ios_base

Referenz
class ios_base {
public:
class failure;
typedef T1 fmtflags;
static const fmtflags boolalpha;
static const fmtflags dec;
static const fmtflags fixed;
static const fmtflags hex;
static const fmtflags internal;
static const fmtflags left;
static const fmtflags oct;
static const fmtflags right;
static const fmtflags scientific;
static const fmtflags showbase;
static const fmtflags showpoint;
static const fmtflags showpos;
static const fmtflags skipws;
static const fmtflags unitbuf;
static const fmtflags uppercase;
static const fmtflags adjustfield;
static const fmtflags basefield;
static const fmtflags floatfield;

typedef T2 iostate;
static const iostate badbit;
static const iostate eofbit;
static const iostate failbit;
static const iostate goodbit;
typedef T3 openmode;
static const openmode app;
static const openmode ate;
static const openmode binary;
static const openmode in;
static const openmode out;
static const openmode trunc;
typedef T4 seekdir;
static const seekdir beg;
static const seekdir cur;
static const seekdir end;
class Init;
// Formatierungflags:
fmtflags flags() const;
fmtflags flags(fmtflags fmtfl);
fmtflags setf(fmtflags fmtfl);
fmtflags setf(fmtflags fmtfl, fmtflags mask);
void unsetf(fmtflags mask);
streamsize precision() const;
streamsize precision(streamsize prec);
streamsize width() const;

403
Die C++-Standardbibliothek

streamsize width(streamsize wide);


// Lokale:
locale imbue(const locale& loc);
locale getloc() const;
// Speicher:
static int xalloc();
long& iword(int index);
void*& pword(int index);
~ios_base();
enum event { erase_event, imbue_event, copyfmt_event };
typedef void (*event_callback)(event, ios_base&, int index);
void register_callback(event_call_back fn, int index);
static bool sync_with_stdio(bool sync = true);
protected:
ios_base();
};

Verweise
Siehe Kategorie Ein- und Ausgabe, Streams in C++

basic_ios
aus <ios>

Beschreibung
Basisklassentemplate für die Stream-Klassen. Enthält allgemeine Routinen zur Kontrolle des
Streams und seines beigeordneten Pufferobjekts (des Klassentemplates basic_streambuf).
Das Klassentemplate basic_ios definiert
– einige höhere Funktionen zum Abfragen der wichtigsten Statusinformationen (good(),
eof(), fail(), bad(), bool(), rdstate() und den Operator !).
– die Funktionen für den Zugriff und den Austausch des Pufferobjekts (rdbuf()) und verknüpf-
ter Ausgabe-Streams (tie()).

Referenz
template <class charT, class traits = char_traits<charT> >
class basic_ios : public ios_base {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef traits traits_type;
operator void*() const
bool operator!() const

404
basic_streambuf

iostate rdstate() const;


void clear(iostate state = goodbit);
void setstate(iostate state);
bool good() const;
bool eof() const;
bool fail() const;
bool bad() const;
iostate exceptions() const;
void exceptions(iostate except);
// Konstruktor:
explicit basic_ios(basic_streambuf<charT,traits>* sb);
virtual ~basic_ios();
basic_ostream<charT,traits>* tie() const;
basic_ostream<charT,traits>* tie(basic_ostream<charT,traits>* tiestr);
basic_streambuf<charT,traits>* rdbuf() const;
basic_streambuf<charT,traits>*
rdbuf(basic_streambuf<charT,traits>* sb);
basic_ios& copyfmt(const basic_ios& rhs);
char_type fill() const;
char_type fill(char_type ch);
// Lokale:
locale imbue(const locale& loc);
char narrow(char_type c, char dfault) const;
char_type widen(char c) const;
protected:
basic_ios();
void init(basic_streambuf<charT,traits>* sb);
};

basic_streambuf
aus <streambuf>

Beschreibung
Das Klassentemplate basic_streambuf ist das Basistemplate für alle Streampuffer
(basic_filebuf, basic_stringbuf). Das Klassentemplate basic_streambuf und die abgeleite-
ten Streampuffer dienen dazu, Zeichensequenzen im Arbeitsspeicher zu kontrollieren. Jede
Instanz verfügt dabei nach Bedarf über Speicherbereiche zur Zeicheneingabe wie zur Zeichen-
ausgabe. Auf jede dieser Zeichensequenzen weisen drei Zeiger:
– Ein Zeiger auf das erste Element der Sequenz.
– Ein Zeiger auf die nächste Adresse, von der gelesen oder in die geschrieben wird.
– Ein Zeiger auf die nächste Elementadresse hinter dem Ende der Sequenz.

405
Die C++-Standardbibliothek

Durch die Verbindung mit einem Stream wird der Puffer mit einer Ausgabe- oder Eingabeein-
heit verknüpft. Zum Zugriff auf die Zeichen im Puffer benutzen die High-level-Funktionen der
Stream-Klasse die Low-level-Funktionen des assoziierten Pufferobjekts.
Die Zwischenschaltung von Pufferobjekten ermöglicht eine gepufferte Ein- und Ausgabe. Dies
bedeutet, daß – beispielsweise beim Lesen aus einer Datei – nicht jeder Leseaufruf des Pro-
gramms mit einem Festplattenzugriff verbunden ist. Statt dessen werden größere Teile der
Datei in den Puffer im Arbeitsspeicher geladen, und die Leseoperationen des Programms wer-
den auf diesem Puffer ausgeführt, bis er vollständig ausgelesen wurde und erneut von der Fest-
platte her aufgefüllt wird. Die verringerte Zahl der Festplattenzugriffe verbessert die Laufzeit
wesentlich, bedeutet aber auch, daß Daten verloren gehen können, wenn bei unerwartetem
Programmabbruch der Puffer nicht geleert ist. Der Abgleich von Puffer und Ein- oder Ausgabe-
einheit kann durch einen Aufruf von pubsync() erreicht werden.

Anwendung
Die Klassen des Templates können nicht direkt instanziiert werden, da sie keinen
public Konstruktor enthalten.
Die Pufferklassen kontrollieren den internen Puffer und bilden somit die Schnitt-
stelle zwischen Stream und Puffer. Dies funktioniert auch, wenn die Streams, die
Größe des internen Puffer des Pufferobjekts auf 0 setzen (siehe Methode pubset-
buf()) – in diesem Fall erhält man eine ungepufferte Ein- oder Ausgabe (die aber
weiterhin über die Instanz der Pufferklasse erfolgt)).

Referenz
template <class charT, class traits = char_traits<charT> >
class basic_streambuf {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
typedef traits traits_type;
virtual ~basic_streambuf();
// Lokale:
locale pubimbue(const locale &loc);
locale getloc() const;
// Puffer:
basic_streambuf<char_type,traits>* pubsetbuf(char_type* s,
streamsize n);
pos_type pubseekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which=ios_base::in|ios_base::out);
pos_type pubseekpos(pos_type sp,
ios_base::openmode which=ios_base::in| os_base::out);
int pubsync();

streamsize in_avail();
int_type snextc();

406
basic_istream

int_type sbumpc();
int_type sgetc();
streamsize sgetn(char_type* s, streamsize n);
int_type sputbackc(char_type c);
int_type sungetc();
int_type sputc(char_type c);
streamsize sputn(const char_type* s, streamsize n);
protected:
basic_streambuf();
char_type* eback() const;
char_type* gptr() const;
char_type* egptr() const;
void gbump(int n);
void setg(char_type* gbeg, char_type* gnext, char_type* gend);
char_type* pbase() const;
char_type* pptr() const;
char_type* epptr() const;
void pbump(int n);
void setp(char_type* pbeg, char_type* pend);
// Virtuelle Funktionen:
virtual void imbue(const locale &loc);
// Pufferverwaltung:
virtual basic_streambuf<char_type,traits>*
setbuf(char_type* s, streamsize n);
virtual pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which = ios_base::in | ios_base::out);
virtual pos_type seekpos(pos_type sp,
ios_base::openmode which = ios_base::in | ios_base::out);
virtual int sync();
virtual int showmanyc();
virtual streamsize xsgetn(char_type* s, streamsize n);
virtual int_type underflow();
virtual int_type uflow();
virtual int_type pbackfail(int_type c = traits::eof());
virtual streamsize xsputn(const char_type* s, streamsize n);
virtual int_type overflow (int_type c = traits::eof());
};

basic_istream
aus <istream>

Beschreibung
Das Klassentemplate basic_istream stellt die höheren Funktionen und Operatoren zum Einle-
sen aus einem Pufferobjekt zur Verfügung. Das Pufferobjekt selbst wird mit der eigentlichen
Eingabeeinheit (der Quelle des Datenflusses) assoziiert. Für cin ist dies standardmäßig die
Tastatur (stdin).

407
Die C++-Standardbibliothek

basic_istream ist die Basisklasse von basic_ifstream (Einlesen aus Datei) und
basic_istringstream (Einlesen von basic_string-Objekten), und sie kann selbst instanziiert
werden, um Stream-Objekte zum komfortablen, formatierten oder unformatierten Einlesen ein-
zurichten. In diesem Sinne sind die Instanzen cin und win zum Einlesen von char- bzw.
wchar_t-Zeichen von der Tastatur in iostream vordefiniert.

Anwendung
Der erste Schritt zur Erzeugung eines Eingabe-Streams ist, das Template
basic_istream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen char und
wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iostream:
typedef basic_istream<char> istream;
typedef basic_istream<wchar_t> wistream;
Der zweite Schritt ist, durch Instanziierung der Stream-Klasse ein Eingabe-Stream-
Objekt zu erzeugen. Dabei muß dem Konstruktor ein Pufferobjekt übergeben wer-
den:
filebuf datei;
[Link]("[Link]", ios_base::in | ios_base::out);
istream dat_ein(&datei);
Für die Instanziierung des Eingabe-Streams cin, der mit der Standardeingabe zu
verbinden ist, sorgt die Implementierung durch den Compilerbauer.

Referenz
template <class charT, class traits = char_traits<charT> >
class basic_istream : virtual public basic_ios<charT,traits> {
public:
// Konstruktoren:
explicit basic_istream(basic_streambuf<charT,traits>* sb);
virtual ~basic_istream();
class sentry;
// Formatierte Eingabe:
basic_istream<charT,traits>& operator>>
(basic_istream<charT,traits>& (*pf)(basic_istream<charT,traits>&))
basic_istream<charT,traits>& operator>>
(basic_ios<charT,traits>& (*pf)(basic_ios<charT,traits>&))
basic_istream<charT,traits>& operator>> (ios_base& (*pf)(ios_base&))
basic_istream<charT,traits>& operator>>(bool& n);
basic_istream<charT,traits>& operator>>(short& n);
basic_istream<charT,traits>& operator>>(unsigned short& n);
basic_istream<charT,traits>& operator>>(int& n);
basic_istream<charT,traits>& operator>>(unsigned int& n);
basic_istream<charT,traits>& operator>>(long& n);
basic_istream<charT,traits>& operator>>(unsigned long& n);
basic_istream<charT,traits>& operator>>(float& f);
basic_istream<charT,traits>& operator>>(double& f);
basic_istream<charT,traits>& operator>>(long double& f);

408
basic_ostream

basic_istream<charT,traits>& operator>>(void*& p);


basic_istream<charT,traits>& operator>>
(basic_streambuf<char_type,traits>* sb);
// Unformatierte Eingabe:
streamsize gcount() const;
int_type get();
basic_istream<charT,traits>& get(char_type& c);
basic_istream<charT,traits>& get(char_type* s, streamsize n);
basic_istream<charT,traits>& get(char_type* s, streamsize n,
char_type delim);
basic_istream<charT,traits>& get(basic_streambuf<char_type,traits>& sb);
basic_istream<charT,traits>& get(basic_streambuf<char_type,traits>& sb,
char_type delim);
basic_istream<charT,traits>& getline(char_type* s, streamsize n);
basic_istream<charT,traits>& getline(char_type* s, streamsize n,
char_type delim);
basic_istream<charT,traits>& ignore
(streamsize n = 1, int_type delim = traits::eof());
int_type peek();
basic_istream<charT,traits>& read (char_type* s, streamsize n);
streamsize readsome(char_type* s, streamsize n);
basic_istream<charT,traits>& putback(char_type c);
basic_istream<charT,traits>& unget();
int sync();
pos_type tellg();
basic_istream<charT,traits>& seekg(pos_type);
basic_istream<charT,traits>& seekg(off_type, ios_base::seekdir);
};

basic_ostream
aus <ostream>

Beschreibung
Das Klassentemplate basic_ostream stellt die höheren Funktionen und Operatoren zum Schrei-
ben in ein Pufferobjekt zur Verfügung. Das Pufferobjekt selbst wird mit der eigentlichen Ausga-
beeinheit (dem Ziel des Datenflusses) assoziiert. Für cout ist dies standardmäßig der
Konsolenbildschirm (stdout).
basic_ostream ist die Basisklasse von basic_ofstream (Schreiben in Datei) und
basic_ostringstream (Schreiben in basic_string-Objekte), und sie kann selbst instanziiert
werden, um Stream-Objekte zur komfortablen, formatierten oder unformatierten Ausgabe ein-
zurichten. In diesem Sinne sind die Instanzen cout, cerr, clog und wout, werr, wlog zur Ausgabe
von char- bzw. wchar_t-Zeichen auf den Bildschirm in iostream vordefiniert.

409
Die C++-Standardbibliothek

Anwendung
Der erste Schritt zur Erzeugung eines Ausgabe-Streams ist, das Template
basic_ostream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen char und
wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iostream:
typedef basic_ostream<char> ostream;
typedef basic_ostream<wchar_t> wostream;
Der zweite Schritt ist, durch Instanziierung der Stream-Klasse ein Ausgabe-Stream-
Objekt zu erzeugen. Dabei muß dem Konstruktor ein Pufferobjekt übergeben wer-
den:
filebuf datei;
[Link]("[Link]", ios_base::in | ios_base::out);
ostream dat_aus(&datei);
Für die Instanziierung des Ausgabe-Streams cout, der mit der Standardausgabe zu
verbinden ist, sorgt die Implementierung durch den Compilerbauer.

Referenz
template <class charT, class traits = char_traits<charT> >
class basic_ostream : virtual public basic_ios<charT,traits> {
public:
// Konstruktoren:
explicit basic_ostream(basic_streambuf<char_type,traits>* sb);
virtual ~basic_ostream();
class sentry;
// Formatierte Ausgabe:
basic_ostream<charT,traits>& operator<<
(basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
basic_ostream<charT,traits>& operator<<
(basic_ios<charT,traits>& (*pf)(basic_ios<charT,traits>&));
basic_ostream<charT,traits>& operator<<
(ios_base& (*pf)(ios_base&));
basic_ostream<charT,traits>& operator<<(bool n);
basic_ostream<charT,traits>& operator<<(short n);
basic_ostream<charT,traits>& operator<<(unsigned short n);
basic_ostream<charT,traits>& operator<<(int n);
basic_ostream<charT,traits>& operator<<(unsigned int n);
basic_ostream<charT,traits>& operator<<(long n);
basic_ostream<charT,traits>& operator<<(unsigned long n);
basic_ostream<charT,traits>& operator<<(float f);
basic_ostream<charT,traits>& operator<<(double f);
basic_ostream<charT,traits>& operator<<(long double f);
basic_ostream<charT,traits>& operator<<(void* p);
basic_ostream<charT,traits>& operator<<
(basic_streambuf<char_type,traits>* sb);
// Unformatierte Ausgabe:
basic_ostream<charT,traits>& put(char_type c);
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);

410
basic_iostream

basic_ostream<charT,traits>& flush();
// Suchen:
pos_type tellp();
basic_ostream<charT,traits>& seekp(pos_type);
basic_ostream<charT,traits>& seekp(off_type, ios_base::seekdir);
};

basic_iostream
aus <istream>

Beschreibung
Das Template ist von basic_istream und basic_ostream abgeleitet und definiert außer Kon-
struktor und Destruktor keine eigenen Elemente.

Anwendung
Das Klassentemplate wird zur Ein- und Ausgabe in einen zugrundeliegenden Puffer
verwendet.

Referenz
template <class charT, class traits = char_traits<charT> >
class basic_iostream :
public basic_istream<charT,traits>,
public basic_ostream<charT,traits> {
public:
explicit basic_iostream(basic_streambuf<charT,traits>* sb);
virtual ~basic_iostream();
};

basic_stringbuf
aus <sstream>

Beschreibung
Das Klassentemplate basic_stringbuf ist von basic_streambuf abgeleitet, um die Eingabe-
oder Ausgabesequenz des Pufferobjekts mit einem basic_string-Objekt zu verbinden.
basic_stringbuf stellt die Pufferobjekte für Stringstreams (basic_istringstream,
basic_ostringstream und basic_stringstream).

411
Die C++-Standardbibliothek

Anwendung
Unter den public-Methoden der Klasse basic_stringbuf finden sich die Methoden,
die die Verbindung zwischen String und Puffer herstellen:
● Die Konstruktoren dienen dazu, das Pufferobjekt einzurichten und eventuell
die Zeiger der Eingabe- oder Ausgabesequenz nach Maßgabe eines übergebe-
nen basic_string-Objekts zu initialisieren.
● str() dient dazu, aus der Eingabe- oder Ausgabesequenz ein basic_string-Ob-
jekt zu erzeugen.
● str(const basic_string<char_type>&) dient dazu, den Puffer mit einem
basic_string-Objekt zu initialisieren.

Referenz
template <class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_stringbuf : public basic_streambuf<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
// Konstruktoren:
explicit basic_stringbuf(ios_base::openmode which
= ios_base::in | ios_base::out);
explicit basic_stringbuf(
const basic_string<charT,traits,Allocator>& str,
ios_base::openmode which = ios_base::in | ios_base::out);
// Zugriff auf String:
basic_string<charT,traits,Allocator> str() const;
void str(const basic_string<charT,traits,Allocator>& s);
protected:
virtual int_type underflow();
virtual int_type pbackfail(int_type c = traits::eof());
virtual int_type overflow (int_type c = traits::eof());
virtual basic_streambuf<charT,traits>* setbuf(charT*, streamsize);
virtual pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which
= ios_base::in | ios_base::out);
virtual pos_type seekpos(pos_type sp,
ios_base::openmode which
= ios_base::in | ios_base::out);
};

412
basic_istringstream

basic_istringstream
aus <sstream>
Stream-Klasse zum Einlesen aus basic_string-Objekten. Benutzt als Pufferobjekt
eine Instanz der Klasse basic_stringbuf.

Anwendung
Der erste Schritt zur Erzeugung eines Stringstreams ist, das Template
basic_istringstream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen
char und wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iosfwd:
typedef basic_istringstream<char> istringstream;
typedef basic_istringstream<wchar_t> wistringstream;
Der zweite Schritt ist aus der Stream-Klasse ein Stringstream-Objekt zu erzeugen:
istringstream str("Hallo");
char s[10];
str >> s;
Mit den beiden str()-Methoden kann man das zugrundeliegende basic_string-
Objekt setzen oder zurückliefern. Ansonsten verwendet man zum Einlesen den >>-
Operator und die anderen von basic_istream geerbten Methoden.

Referenz
template <class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_istringstream : public basic_istream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
explicit basic_istringstream(ios_base::openmode which =ios_base::in);
explicit basic_istringstream(
const basic_string<charT,traits,Allocator>& str,
ios_base::openmode which = ios_base::in);
basic_stringbuf<charT,traits,Allocator>* rdbuf() const;
basic_string<charT,traits,Allocator> str() const;
void str(const basic_string<charT,traits,Allocator>& s);
};

413
Die C++-Standardbibliothek

basic_ostringstream
aus <sstream>
Stream-Klasse zur Ausgabe in basic_string-Objekte. Benutzt als Pufferobjekt eine
Instanz der Klasse basic_stringbuf.

Anwendung
Der erste Schritt zur Erzeugung eines Stringstreams ist, das Template
basic_ostringstream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen
char und wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iosfwd:
typedef basic_ostringstream<char> ostringstream;
typedef basic_ostringstream<wchar_t> wostringstream;
Der zweite Schritt ist aus der Stream-Klasse ein Stringstream-Objekt zu erzeugen:
ostringstream str;
str << "Hallo";
Mit den beiden str()-Methoden kann man das zugrundeliegene basic_string-
Objekt setzen oder zurückliefern. Ansonsten verwendet man zum Schreiben den
<<-Operator und die anderen von basic_ostream geerbten Methoden.

Referenz
template <class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_ostringstream : public basic_ostream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
explicit basic_ostringstream(ios_base::openmode which=ios_base::out);
explicit basic_ostringstream(
const basic_string<charT,traits,Allocator>& str,
ios_base::openmode which = ios_base::out);
virtual ~basic_ostringstream();
basic_stringbuf<charT,traits,Allocator>* rdbuf() const;
basic_string<charT,traits,Allocator> str() const;
void str(const basic_string<charT,traits,Allocator>& s);
};

414
basic_stringstream

basic_stringstream
aus <sstream>

Beschreibung
Stream-Klasse zur Ein- und Ausgabe in basic_string-Objekte. Benutzt als Pufferobjekt eine
Instanz der Klasse basic_stringbuf.

Anwendung
Mit den beiden überladenen Methoden str() kann man das zugrundeliegende
basic_string-Objekt setzen oder zurückliefern.
Ansonsten verwendet man die Streamoperatoren und die anderen von
basic_iostream geerbten Methoden.

Referenz
template <class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_stringstream : public basic_iostream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
// Konstruktoren
explicit basic_stringstream(
ios_base::openmode which = ios_base::out|ios_base::in);
explicit basic_stringstream(
const basic_string<charT,traits,Allocator>& str,
ios_base::openmode which = ios_base::out|ios_base::in);
// Zugriff auf Puffer und String:
basic_stringbuf<charT,traits,Allocator>* rdbuf() const;
basic_string<charT,traits,Allocator> str() const;
void str(const basic_string<charT,traits,Allocator>& str);
};

basic_filebuf
aus <fstream>

Beschreibung
Das Klassentemplate basic_filebuf ist von basic_streambuf abgeleitet, um die Eingabe- oder
Ausgabesequenz des Pufferobjekts mit einer Datei zu verbinden.

415
Die C++-Standardbibliothek

Sie spezialisiert die Klasse basic_streambuf für die Erzeugung von Pufferobjekten, die mit
Dateien verbunden werden, und stellt die Pufferobjekte für Objekte der Klassentemplates
basic_ifstream, basic_ofstream und basic_fstream.

Anwendung
Unter den public-Methoden der Klasse basic_filebuf finden sich die Methoden, die
die Verbindung zwischen Datei und Puffer herstellen:
● open() zum Öffnen einer Datei.
● close() zum Schließen einer Datei.
filebuf datei; // filebuf ist gleich basic_filebuf<char>
[Link]("[Link]", ios_base::in | ios_base::out);
[Link]();

Referenz
template <class charT, class traits = char_traits<charT> >
class basic_filebuf : public basic_streambuf<charT,traits> {
public:
basic_filebuf();
virtual ~basic_filebuf();
bool is_open() const;
basic_filebuf<charT,traits>* open(const char* s,
ios_base::openmode mode);
basic_filebuf<charT,traits>* close();
protected:
virtual int showmanyc();
virtual int_type underflow();
virtual int_type uflow();
virtual int_type pbackfail(int_type c = traits::eof());
virtual int_type overflow (int_type c = traits::eof());
virtual basic_streambuf<charT,traits>* setbuf(char_type* s,
streamsize n);
virtual pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which
= ios_base::in | ios_base::out);
virtual pos_type seekpos(pos_type sp, ios_base::openmode which
= ios_base::in | ios_base::out);
virtual int sync();
virtual void imbue(const locale& loc);
};

416
basic_ifstream

basic_ifstream
aus <fstream>

Beschreibung
Das Klassentemplate basic_ifstream stellt die Funktionen zum Öffnen und Schließen von
Dateien zur Verfügung.

Anwendung
Der erste Schritt zur Erzeugung eines Eingabe-Streams für eine Datei ist, das Tem-
plate basic_ifstream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen
char und wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iostream:
typedef basic_ifstream<char> ifstream;
typedef basic_ifstream<wchar_t> wifstream;
Der zweite Schritt ist durch Instanziierung der Stream-Klasse ein Eingabe-Stream-
Objekt zu erzeugen. Dabei muß dem Konstruktor ein Pufferobjekt übergeben wer-
den:
ifstream dat_ein;
dat_ein.open("dateiname", ios_base::in);
Die eigentlichen Lesemethoden werden von basic_istream geerbt.

Referenz
template <class charT, class traits = char_traits<charT> >
class basic_ifstream : public basic_istream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
basic_ifstream();
explicit basic_ifstream(const char* s,
ios_base::openmode mode = ios_base::in);
basic_filebuf<charT,traits>* rdbuf() const;
bool is_open();
void open(const char* s, openmode mode = in);
void close();
};

417
Die C++-Standardbibliothek

basic_ofstream
aus <fstream>

Beschreibung
Das Klassentemplate basic_ofstream stellt die Funktionen zum Öffnen und Schließen von
Dateien zur Verfügung.

Anwendung
Der erste Schritt zur Erzeugung eines Ausgabe-Streams für eine Datei ist, das Tem-
plate basic_ofstream für einen Zeichentyp zu spezialisieren. Für die Zeichentypen
char und wchar_t ist dies bereits geschehen. Die Typdefinitionen stehen in iostream:
typedef basic_ofstream<char> ofstream;
typedef basic_ofstream<wchar_t> wofstream;
Der zweite Schritt ist durch Instanziierung der Stream-Klasse ein Ausgabe-Stream-
Objekt zu erzeugen. Dabei muß dem Konstruktor ein Pufferobjekt übergeben wer-
den:
ofstream dat_aus;
dat_aus.open("dateiname", ios_base::out);
Die eigentlichen Schreibmethoden werden von basic_ostream geerbt.

Referenz
template <class charT, class traits = char_traits<charT> >
class basic_ofstream : public basic_ostream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type int_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
basic_ofstream();
explicit basic_ofstream(const char* s,
ios_base::openmode mode = ios_base::out|ios_base::trunc);
basic_filebuf<charT,traits>* rdbuf() const;
bool is_open();
void open(const char* s, ios_base::openmode mode = out | trunc);
void close();
};

418
basic_fstream

basic_fstream
aus <fstream>

Beschreibung
Stream-Klasse zur Ein- und Ausgabe in Dateien. Benutzt als Pufferobjekt eine Instanz der
Klasse basic_filebuf.

Anwendung
Mit den Methoden open() und close() kann man Dateien öffnen und schließen.
Für die Ein- und Ausgabe verwendet man die Stream-Operatoren und die anderen
von basic_iostream geerbten Methoden.

Referenz
template <class charT, class traits=char_traits<charT> >
class basic_fstream : public basic_iostream<charT,traits> {
public:
typedef charT char_type;
typedef typename traits::int_type ins_type;
typedef typename traits::pos_type pos_type;
typedef typename traits::off_type off_type;
// Konstruktoren
basic_fstream();
explicit basic_fstream(const char* s,
ios_base::openmode mode = ios_base::in|ios_base::out);
// Zugriff auf Puffer und Dateien:
basic_filebuf<charT,traits>* rdbuf() const;
bool is_open();
void open(const char* s,
ios_base::openmode mode = ios_base::in|ios_base::out);
void close();
};

419
Die C++-Standardbibliothek

Die String-Klassen

Übersicht
Beschreibung
Das Klassentemplate basic_string stellt die objektorientierte Alternative zu den ANSI C-Funk-
tionen aus string.h dar. Die Implementierung als Template erlaubt es, Strings für jedweden
Zeichentyp zu erzeugen.
Um die Klasse typenunabhängig implementieren zu können, wurden – wie bei den iostream-
Klassen – die grundlegenden, vom verwendeten Zeichentyp abhängigen Routinen in eine
traits-Klasse ausgelagert. Der Zeichentyp und seine traits-Klasse werden dann den Template-
Instanzen von basic_string als Template-Parameter übergeben.

Anwendung
Für die Zeichentypen char und wchar_t sind in der Laufzeitbibliothek bereits Spezia-
lisierungen des traits-Templates sowie Typdefinitionen von basic_string-Spezialisie-
rungen definiert. Letztere heißen string und wstring.
Die wichtigsten Stringmanipulationen sind in basic_string als Methoden und/oder
Operatoren implementiert.
Durch die globale Überladung der Operatoren + (Konkatenation), == , !=, <, <=, >,
>= (für Vergleiche), sowie >> und << (Ein- und Ausgabe), wird der Umgang mit
Zeichenketten noch weiter vereinfacht.

Verweise
Siehe Kategorie Zeichenketten, Die Klasse String

char_traits
aus <string>

Beschreibung
Eine Template-Struktur, die Methoden und Typdefinitionen enthält, deren Definition vom über-
gebenen Zeichentyp charT abhängt und die für die Implementierung des basic_string-Tem-
plates notwendig sind. Auf diese Weise kann die Implementierung des Templates basic_string
unabhängig von den zu manipulierenden Zeichen gehalten werden.
Spezialisierungen des Templates werden als Template-Argument für basic_string und die
Stream-Klassen verwendet.

420
basic_string

Referenz
template<> struct char_traits<char> {
typedef char char_type;
typedef int int_type;
typedef streamoff off_type;
typedef streampos pos_type;
typedef mbstate_t state_type;

static void assign(char_type& c1, const char_type& c2);


static bool eq(const char_type& c1, const char_type& c2);
static bool lt(const char_type& c1, const char_type& c2);
static int compare(const char_type* s1, const char_type* s2, size_t n);
static size_t length(const char_type* s);
static const char_type* find(const char_type* s, int n,
const char_type& a);
static char_type* move(char_type* s1, const char_type* s2, size_t n);
static char_type* copy(char_type* s1, const char_type* s2, size_t n);
static char_type* assign(char_type* s, size_t n, char_type a);
static int_type not_eof(const int_type& c);
static char_type to_char_type(const int_type& c);
static int_type to_int_type(const char_type& c);
static bool eq_int_type(const int_type& c1, const int_type& c2);
static state_type get_state(pos_type pos);
static int_type eof();
};

basic_string
aus <string>

Beschreibung
Die Klasse unterstützt die Programmierung mit Zeichenketten und bietet eine Fülle an Funktio-
nen zu deren Erzeugung und Manipulation.
Im einzelnen sind das Template-Funktionen
● zur Erzeugung von Strings,
● zum Zuweisen, Anhängen und Einfügen,
● zum Löschen, Entfernen und Ersetzen,
● zur Ermittlung der Größe der Zeichenketten,
● zum indizierten Zugriff auf einzelne Zeichen im String,
● zum Vergleich von Zeichenketten,
● zum Suchen von Zeichen und Teil-Strings.

421
Die C++-Standardbibliothek

Wo dies sinnvoll ist, sind die Funktionen überladen, meist um neben Zeichenketten
auch einzelne Zeichen oder basic_string-Objekte als Argument zu akzeptieren,
oder um mit Iteratoren arbeiten zu können.

Anwendung
Der Gebrauch der Klasse erfolgt einfach durch Spezialisierung des Klassentempla-
tes für den zu verwendenden Zeichentyp. Für char und wchar_t ist dies bereits
geschehen, die entsprechenden String-Typen lauten
string und
wstring
Für diese Klassen können Objekte erzeugt werden, die dann über ihre Methoden
und Operatoren manipuliert werden können.

Referenz
template<class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT> >
class basic_string {
public:
typedef traits traits_type;
typedef typename traits::char_type value_type;
typedef Allocator allocator_type;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;
typedef implementation defined iterator;
typedef implementation defined const_iterator
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
static const size_type npos = -1;
// Konstruktoren, Kopieren:
explicit basic_string(const Allocator& a = Allocator());
basic_string(const basic_string& str, size_type pos = 0,
size_type n = npos, const Allocator& a = Allocator());
basic_string(const charT* s, size_type n, const Allocator& a =
Allocator());
basic_string(const charT* s, const Allocator& a = Allocator());
basic_string(size_type n, charT c, const Allocator& a = Allocator());
template<class InputIterator>
basic_string(InputIterator begin, InputIterator end,
const Allocator& a = Allocator());
~basic_string();
basic_string& operator=(const basic_string& str);
basic_string& operator=(const charT* s);

422
basic_string

basic_string& operator=(charT c);

// Iteratoren:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
// Größe:
size_type size() const;
size_type length() const;
size_type max_size() const;
void resize(size_type n, charT c);
void resize(size_type n);
size_type capacity() const;
void reserve(size_type res_arg = 0);
void clear();
bool empty() const;
// Zugriff auf Zeichen:
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
const_reference at(size_type n) const;
reference at(size_type n);

// Verändernde Operationen:
basic_string& operator+=(const basic_string& str);
basic_string& operator+=(const charT* s);
basic_string& operator+=(charT c);
basic_string& append(const basic_string& str);
basic_string& append(const basic_string& str, size_type pos,
size_type n);
basic_string& append(const charT* s, size_type n);
basic_string& append(const charT* s);
basic_string& append(size_type n, charT c);
template<class InputIterator>
basic_string& append(InputIterator first, InputIterator last);
basic_string& assign(const basic_string&);
basic_string& assign(const basic_string& str, size_type pos,
size_type n);
basic_string& assign(const charT* s, size_type n);
basic_string& assign(const charT* s);
basic_string& assign(size_type n, charT c);
template<class InputIterator>
basic_string& assign(InputIterator first, InputIterator last);

basic_string& insert(size_type pos1, const basic_string& str);


basic_string& insert(size_type pos1, const basic_string& str,
size_type pos2, size_type n);

423
Die C++-Standardbibliothek

basic_string& insert(size_type pos, const charT* s, size_type n);


basic_string& insert(size_type pos, const charT* s);
basic_string& insert(size_type pos, size_type n, charT c);
iterator insert(iterator p, charT c = charT());
void insert(iterator p, size_type n, charT c);
template<class InputIterator>
void insert(iterator p, InputIterator first, InputIterator last);
basic_string& erase(size_type pos = 0, size_type n = npos);
iterator erase(iterator position);
iterator erase(iterator first, iterator last);
basic_string& replace(size_type pos1, size_type n1,
const basic_string& str);
basic_string& replace(size_type pos1, size_type n1,
const basic_string& str, size_type pos2, size_type n2);
basic_string& replace(size_type pos, size_type n1, const charT* s,
size_type n2);
basic_string& replace(size_type pos, size_type n1, const charT* s);
basic_string& replace(size_type pos, size_type n1, size_type n2,
charT c);
basic_string& replace(iterator i1, iterator i2,
const basic_string& str);
basic_string& replace(iterator i1, iterator i2, const charT* s,
size_type n);
basic_string& replace(iterator i1, iterator i2, const charT* s);
basic_string& replace(iterator i1, iterator i2,
size_type n, charT c);
template<class InputIterator>
basic_string& replace(iterator i1, iterator i2,
InputIterator j1, InputIterator j2);
size_type copy(charT* s, size_type n, size_type pos = 0) const;
void swap(basic_string<charT,traits,Allocator>&);

// Nicht verändernde Operationen:


const charT* c_str() const;
const charT* data() const;
allocator_type get_allocator() const;
size_type find (const basic_string& str, size_type pos = 0) const;
size_type find (const charT* s, size_type pos, size_type n) const;
size_type find (const charT* s, size_type pos = 0) const;
size_type find (charT c, size_type pos = 0) const;
size_type rfind(const basic_string& str, size_type pos = npos) const;
size_type rfind(const charT* s, size_type pos, size_type n) const;
size_type rfind(const charT* s, size_type pos = npos) const;
size_type rfind(charT c, size_type pos = npos) const;
size_type find_first_of(const basic_string& str, size_type pos = 0)
const;
size_type find_first_of(const charT* s, size_type pos, size_type n)
const;
size_type find_first_of(const charT* s, size_type pos = 0) const;
size_type find_first_of(charT c, size_type pos = 0) const;
size_type find_last_of (const basic_string& str,

424
Übersicht

size_type pos = npos) const;


size_type find_last_of (const charT* s, size_type pos, size_type n)
const;
size_type find_last_of (const charT* s, size_type pos = npos) const;
size_type find_last_of (charT c, size_type pos = npos) const;
size_type find_first_not_of(const basic_string& str,
size_type pos = 0) const;
size_type find_first_not_of(const charT* s, size_type pos,
size_type n) const;
size_type find_first_not_of(const charT* s, size_type pos = 0) const;
size_type find_first_not_of(charT c, size_type pos = 0) const;
size_type find_last_not_of (const basic_string& str,
size_type pos = npos) const;
size_type find_last_not_of (const charT* s, size_type pos,
size_type n) const;
size_type find_last_not_of (const charT* s, size_type pos = npos)
const;
size_type find_last_not_of (charT c, size_type pos = npos) const;
basic_string substr(size_type pos = 0, size_type n = npos) const;
int compare(const basic_string& str) const;
int compare(size_type pos1, size_type n1,
const basic_string& str) const;
int compare(size_type pos1, size_type n1,
const basic_string& str,
size_type pos2, size_type n2) const;
int compare(const charT* s) const;
int compare(size_type pos1, size_type n1,
const charT* s, size_type n2 = npos) const;
};

Verweise
Siehe Kategorie Zeichenketten, Die Klasse String

Die Klassen zur lokalen Einstellung

Übersicht
Beschreibung
Datumsangaben, die Zeichen für nationale Währungseinheiten oder beispielsweise die Zei-
chensetzung in Gleitkommazahlen, sind von Land zu Land verschieden. Auf welche Weise soll
also ein C++-Programm, das sich international verkaufen soll, eine Datumsangabe formatieren?
Die Antwort liegt in der lokalen Einstellung. In ihr sind, nach Kategorien geordnet, die nötigen
Informationen zur länderspezifischen Behandlung abgelegt. Jede Kategorie bündelt wiederum
mehrere Facetten:

425
Die C++-Standardbibliothek

Kategorie Facetten

Klassifizierung und Konvertierung von Zeichen:


ctype ctype<char>, ctype<wchar_t>
codecvt<char,char,mbstate_t>
codecvt<wchar_t,char,mbstate_t>
Vergleich von Zeichen:
collate collate<char>, collate<wchar_t>
Botschaftsverarbeitung:
messages messages<char>, messages<wchar_t>
Formatierung von Währungsangaben:
monetary moneypunct<char>, moneypunct<wchar_t>
moneypunct<char,true>, moneypunct<wchar_t,true>
money_get<char>, money_get<wchar_t>
money_put<char>, money_put<wchar_t>
Zeichensetzung in numerischen Angaben:
numeric numpunct<char>, numpunct<wchar_t>
num_get<stream,InIter>,
num_put<stream,OutputIter>
Datumsangaben:
time time_get<char, InIter>
time_get<wchar_t, InIter>
time_put<char, OutputIterator>
time_put<wchar_t, OutputIterator>

Anwendung
In C++ sind die lokale Einstellung und die einzelnen Facetten durch Klassen reprä-
sentiert. Sie können diese Klassen nutzen, um eigene Facetten zu implementieren,
eigene lokale Einstellungen aus vorhandenen Einstellungen und Facetten zu erstel-
len, zwischen lokalen Einstellungen oder Facetten hin- und herzuschalten.
Sinnvoll ist der Rückgriff auf die lokalen Einstellungen etwa bei der Ein- und Aus-
gabe von Daten. Die Stream-Klassen verfügen daher schon über eigene Methoden
(imbue()) zur Auswahl einer lokalen Einstellung.
Durch entsprechende Implementierungen der Operatoren << und >> können Sie
Programme schreiben, die sich entweder an die lokalen Gegebenheiten (werden
vom Betriebssystem übernommen) anpassen oder deren Formatierung unabhängig
von nationalen Eigenheiten erfolgt.

426
locale

locale
aus <locale>

Beschreibung
Klasse zur Repräsentation und Verwaltung einer locale-Einstellung.
Die Klasse locale definiert:
● Konstruktoren zum Erzeugen neuer locale-Einstellungen, basierend auf ande-
ren locale-Einstellungen.
● Funktionen und Operatoren zum Abfragen von Informationen über die locale-
Einstellung (name(), ==(), !=() sowie die globalen Funktionentemplates
use_facet() und has_facet()).
● Funktionen für globale locale-Einstellungen (global(), classic()).
● Vergleichsfunktion operator() für Zeichenketten.

Anwendung
Mit Hilfe der Klasse locale können Sie eigene locale-Einstellungen kreieren, die Sie
dann beispielsweise mit der Stream-Methode imbue() einem Stream zuweisen kön-
nen, um formatierte Ein- und Ausgaben nach Maßgabe Ihrer locale-Einstellung
vorzunehmen.

Referenz
class locale {
public:
class facet;
class id;
typedef int category;
static const category;
/* none, collate, ctype,
monetary, numeric,
time, messages,
all = collate | ctype | monetary | numeric | time | messages;
*/
// Konstruktoren:
locale() throw();
locale(const locale& other) throw();,
explicit locale(const char* std_name);
locale(const locale& other, const char* std_name, category);
template <class Facet> locale(const locale& other, Facet* f);
template <class Facet> locale(const locale& other,
const locale& one);
locale(const locale& other, const locale& one, category);
~locale() throw(); // non-virtual
const locale& operator=(const locale& other) throw();

427
Die C++-Standardbibliothek

basic_string<char> name() const;


bool operator==(const locale& other) const;
bool operator!=(const locale& other) const;
template <class charT, class Traits, class Allocator>
bool operator()(const basic_string<charT,Traits,Allocator>& s1,
const basic_string<charT,Traits,Allocator>& s2) const;
// globale Lokale:
static locale global(const locale&);
static const locale& classic();
};

Die Hilfsklassen für die einzelnen Kategorien


Anwendung
Mit Hilfe der nachfolgend aufgeführten Klassen können eigene Facetten implemen-
tiert werden. Diese Facetten kann man beispielsweise in eigene Lokale (Instanzen
der Klasse locale) integrieren.

Beispiel
class de_Num : public numpunct_byname<char> {
public:
de_Num(const char* name) : numpunct_byname<char>(name) {}
protected:
virtual char_type do_decimal_point() const {
return ',';
}
};

// Eigene locale mit de_Num-Facette


locale myloc(locale("C"), new de_Num(""));

ctype_base <locale>
Basisklasse zum Klassentemplate ctype, die einen Aufzählungstyp definiert, der als
Maske bei der Zeichenklassifizierung benutzt wird.
class ctype_base {
public:
enum mask {
space, // Nicht-darstellendes Zeichen
print, // Darstellbares Zeichen
cntrl, // Steuerzeichen
upper, // Großbuchstabe
lower, // Kleinbuchstabe
alpha, // Buchstabe
digit, // Ziffer

428
Die Hilfsklassen für die einzelnen Kategorien

punct, // Interpunktionszeichen
xdigit, // Hexadezimalzahl
alnum, // alpha | digit
graph // alnum | punct
};
};

ctype <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie ctype, zur Zeichenklas-
sifizierung und -konvertierung.
Enthält einen Satz von public-Methoden zur Zeichenklassifizierung und -konvertie-
rung. Jeder Funktion entspricht eine virtuelle protected Version, die sie aufruft und
die in abgeleiteten Klassen überschrieben werden kann.
template <class charT>
class ctype : public locale::facet, public ctype_base {
public:
typedef charT char_type;
explicit ctype(size_t refs = 0);
bool is(mask m, charT c) const;
const charT* is(const charT* low, const charT* high, mask* vec) const;
const charT* scan_is(mask m,const charT* low,const charT* high) const;
const charT* scan_not(mask m,const charT* low,const charT* high) const;
charT toupper(charT) const;
const charT* toupper(charT* low, const charT* high) const;
charT tolower(charT c) const;
const charT* tolower(charT* low, const charT* high) const;
charT widen(char c) const;
const char* widen(const char* low, const char* high, charT* to) const;
char narrow(charT c, char dfault) const;
const charT* narrow(const charT* low, const charT*, char dfault,
char* to) const;
static locale::id id;
protected:
~ctype(); // virtual
virtual bool do_is(mask m, charT c) const;
virtual const charT* do_is(const charT* low, const charT* high,
mask* vec) const;
virtual const charT* do_scan_is(mask m,
const charT* low, const charT* high) const;
virtual const charT* do_scan_not(mask m,
const charT* low, const charT* high) const;
virtual charT do_toupper(charT) const;
virtual const charT* do_toupper(charT* low, const charT* high) const;
virtual charT do_tolower(charT) const;
virtual const charT* do_tolower(charT* low, const charT* high) const;
virtual charT do_widen(char) const;
virtual const char* do_widen(const char* low, const char* high,
charT* dest) const;

429
Die C++-Standardbibliothek

virtual char do_narrow(charT, char dfault) const;


virtual const charT* do_narrow(const charT* low, const charT* high,
char dfault, char* dest) const;
};

ctype_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT>
class ctype_byname : public ctype<charT> {
public:
explicit ctype_byname(const char*, size_t refs = 0);
protected:
~ctype_byname(); // virtual
virtual bool do_is(mask m, charT c) const;
virtual const charT* do_is(const charT* low, const charT* high,
mask* vec) const;
virtual const char* do_scan_is(mask m,
const charT* low, const charT* high) const;
virtual const char* do_scan_not(mask m,
const charT* low, const charT* high) const;
virtual charT do_toupper(charT) const;
virtual const charT* do_toupper(charT* low, const charT* high) const;
virtual charT do_tolower(charT) const;
virtual const charT* do_tolower(charT* low, const charT* high) const;
virtual charT do_widen(char) const;
virtual const char* do_widen(const char* low, const char* high,
charT* dest) const;
virtual char do_narrow(charT, char dfault) const;
virtual const charT* do_narrow(const charT* low, const charT* high,
char dfault, char* dest) const;
};

codecvt_base <locale>
Basisklasse zum Klassentemplate codecvt, die einen Aufzählungstyp definiert, der
die verschiedenen Ergebniswerte der Konvertierungsfunktion codecvt::convert()
definiert.
class codecvt_base {
public:
enum result {
ok, // vollständige Konvertierung
partial // nicht genügend Speicher
error // keine Konvertierung möglich
noconv // keine Konvertierung erforderlich
};
};

430
Die Hilfsklassen für die einzelnen Kategorien

codecvt <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie codecvt, zur Konvertie-
rung von Zeichensätzen.
Die Klasse enthält public-Methoden zur Konvertierung von einem Zeichensatz in
einen anderen. Jeder Funktion entspricht eine virtuelle protected Version, die sie
aufruft und die in abgeleiteten Klassen überschrieben werden kann.
template <class internT, class externT, class stateT>
class codecvt : public locale::facet, public codecvt_base {
public:
typedef internT intern_type;
typedef externT extern_type;
typedef stateT state_type;
explicit codecvt(size_t refs = 0);
result out(stateT& state, const internT* from, const internT* from_end,
const internT*& from_next, externT* to,
externT* to_limit, externT*& to_next) const;
result unshift(stateT& state, externT* to,
externT* to_limit, externT*& to_next) const;
result in(stateT& state, const externT* from, const externT* from_end,
const externT*& from_next, internT* to,
internT* to_limit, internT*& to_next) const;
int encoding() const throw();
bool always_noconv() const throw();
int length(const stateT&, const externT* from, const externT* end,
size_t max) const;
int max_length() const throw();
static locale::id id;
protected:
~codecvt(); // virtual
virtual result do_out(stateT& state, const internT* from,
const internT* from_end, const internT*& from_next,
externT* to, externT* to_limit, externT*& to_next) const;
virtual result do_unshift(stateT& state, externT* to,
externT* to_limit, externT*& to_next) const;
virtual result do_in(stateT& state, const externT* from,
const externT* from_end, const externT*& from_next,
internT* to, internT* to_limit,
internT*& to_next) const;
virtual int do_encoding() const throw();
virtual bool do_always_noconv() const throw();
virtual int do_length(const stateT&, const externT* from,
const externT* end, size_t max) const;
virtual int do_max_length() const throw();
};

431
Die C++-Standardbibliothek

codecvt_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class internT, class externT, class stateT>
class codecvt_byname : public codecvt<internT, externT, stateT> {
public:
explicit codecvt_byname(const char*, size_t refs = 0);
protected:
~codecvt_byname(); // virtual
virtual result do_out(stateT& state, const internT* from,
const internT* from_end, const internT*& from_next,
externT* to, externT* to_limit,
externT*& to_next) const;
virtual result do_in(stateT& state, const externT* from,
const externT* from_end, const externT*& from_next,
internT* to, internT* to_limit,
internT*& to_next) const;
virtual int do_encoding() const throw();
virtual bool do_always_noconv() const throw();
virtual int do_length(const stateT&, const externT* from,
const externT* end,size_t max) const;
virtual int do_max_length() const throw();
};

collate <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie collate, zum Vergleich
von Zeichenketten.
Enthält einen Satz von public-Methoden zum Vergleich von Zeichenketten. Jeder
Methode entspricht eine virtuelle protected Version, die sie aufruft und die in abge-
leiteten Klassen überschrieben werden kann.
template <class charT>
class collate : public locale::facet {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit collate(size_t refs = 0);
int compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
string_type transform(const charT* low, const charT* high) const;
long hash(const charT* low, const charT* high) const;
static locale::id id;
protected:
~collate(); // virtual
virtual int do_compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
virtual string_type do_transform(const charT* low,

432
Die Hilfsklassen für die einzelnen Kategorien

const charT* high) const;


virtual long do_hash (const charT* low, const charT* high) const;
};

collate_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT>
class collate_byname : public collate<charT> {
public:
explicit collate_byname(const char*, size_t refs = 0);
protected:
~collate_byname(); // virtual
virtual int do_compare(const charT* low1, const charT* high1,
const charT* low2, const charT* high2) const;
virtual string_type do_transform(const charT* low,
const charT* high) const;
virtual long do_hash( const charT* low, const charT* high) const;
};

messages_base <locale>
Basisklasse zum Klassentemplate messages, die eine Abkürzung für den Typ der Bot-
schaftskataloge definiert.
class messages_base {
public:
typedef int catalog;
};

messages <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie messages, zur Auswahl
von Meldungen aus Katalogen.
Enthält einen Satz von public-Methoden zur Auswahl von Meldungen aus Katalo-
gen. Jeder Funktion entspricht eine virtuelle protected Version, die sie aufruft und
die in abgeleiteten Klassen überschrieben werden kann.
template <class charT>
class messages : public locale::facet, public messages_base {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit messages(size_t refs = 0);
catalog open(const basic_string<char>& fn, const locale&) const;
string_type get(catalog c, int set, int msgid,
const string_type& dfault) const;

433
Die C++-Standardbibliothek

void close(catalog c) const;


static locale::id id;
protected:
~messages(); // virtual
virtual catalog do_open(const basic_string<char>&,
const locale&) const;
virtual string_type do_get(catalog, int set, int msgid,
const string_type& dfault) const;
virtual void do_close(catalog) const;
};

messages_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT>
class messages_byname : public messages<charT> {
public:
explicit messages_byname(const char*, size_t refs = 0);
protected:
~messages_byname(); // virtual

virtual catalog do_open(const basic_string<char>&,


const locale&) const;
virtual string_type do_get(catalog, int set, int msgid,
const string_type& dfault) const;
virtual void do_close(catalog) const;
};

money_get <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie monetary, zum Einlesen
von Währungsangaben.
Enthält public-Methoden zum Einlesen von Währungsangaben. Jeder Methode ent-
spricht eine virtuelle protected Version, die sie aufruft und die in abgeleiteten Klas-
sen überschrieben werden kann.
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class money_get : public locale::facet {
public:
typedef charT char_type;
typedef InputIterator iter_type;
typedef basic_string<charT> string_type;
explicit money_get(size_t refs = 0);
iter_type get(iter_type s, iter_type end, bool intl,
ios_base& f, ios_base::iostate& err,
long double& units) const;
iter_type get(iter_type s, iter_type end, bool intl,

434
Die Hilfsklassen für die einzelnen Kategorien

ios_base& f, ios_base::iostate& err,


string_type& digits) const;
static const bool intl = Intl;
static locale::id id;
protected:
~money_get(); // virtual
virtual iter_type do_get(iter_type, bool, iter_type, ios_base&,
ios_base::iostate& err, long double& units) const;
virtual iter_type do_get(iter_type, bool, iter_type, ios_base&,
ios_base::iostate& err, string_type& digits) const;
};

money_put <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie monetary, zum Ausgeben
von Währungsangaben.
Enthält public-Methoden zum Ausgeben von Währungsangaben. Jeder Funktion
entspricht eine virtuelle protected Version, die sie aufruft und die in abgeleiteten
Klassen überschrieben werden kann.
template <class charT, bool Intl = false,
class OutputIterator = ostreambuf_iterator<charT> >
class money_put : public locale::facet {

public:
typedef charT char_type;
typedef OutputIterator iter_type;
typedef basic_string<charT> string_type;
explicit money_put(size_t refs = 0);
iter_type put(iter_type s, bool intl, ios_base& f,
char_type fill, long double units) const;
iter_type put(iter_type s, bool intl, ios_base& f,
char_type fill, const string_type& digits) const;
static locale::id id;
protected:
~money_put(); // virtual
virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill,
long double units) const;
virtual iter_type do_put(iter_type, bool, ios_base&, char_type fill,
const string_type& digits) const;
};

money_base <locale>
Basisklasse zum Klassentemplate moneypunct, die einen Aufzählungstyp und einen
zugehörigen Strukturtyp definiert, die zur Festlegung der Abfolge von Elementen in
Währungsangaben dienen.
class money_base {
public:

435
Die C++-Standardbibliothek

enum part {
none, // keine Angaben
space, // Nicht darstellendes Zeichen
symbol, // Währungssymbol
sign, // Vorzeichen
value // Wert };
struct pattern { char field[4]; };
};

moneypunct <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie monetary, zur Zeichen-
setzung in Währungsangaben.
Enthält einen Satz von public-Methoden zur Zeichensetzung in Währungsangaben.
Jeder Methode entspricht eine virtuelle protected Version, die sie aufruft und die in
abgeleiteten Klassen überschrieben werden kann.
template <class charT, bool International = false>
class moneypunct : public locale::facet, public money_base {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit moneypunct(size_t refs = 0);
charT decimal_point() const;
charT thousands_sep() const;
string grouping() const;
string_type curr_symbol() const;
string_type positive_sign() const;
string_type negative_sign() const;
int frac_digits() const;
pattern pos_format() const;
pattern neg_format() const;
static locale::id id;
static const bool intl = International;
protected:
~moneypunct(); // virtual
virtual charT do_decimal_point() const;
virtual charT do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_curr_symbol() const;
virtual string_type do_positive_sign() const;
virtual string_type do_negative_sign() const;
virtual int do_frac_digits() const;
virtual pattern do_pos_format() const;
virtual pattern do_neg_format() const;
};

436
Die Hilfsklassen für die einzelnen Kategorien

moneypunct_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT, bool Intl = false>
class moneypunct_byname : public moneypunct<charT, Intl> {
public:
explicit moneypunct_byname(const char*, size_t refs = 0);
protected:
~moneypunct_byname(); // virtual
virtual charT do_decimal_point() const;
virtual charT do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_curr_symbol() const;
virtual string_type do_positive_sign() const;
virtual string_type do_negative_sign() const;
virtual int do_frac_digits() const;
virtual pattern do_pos_format() const;
virtual pattern do_neg_format() const;
};

num_get <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie numeric, zum Einlesen
von numerischen Werten.
Enthält einen Satz von public-Methoden zum Einlesen von numerischen Werten.
Jeder Methode entspricht eine virtuelle protected Version, die sie aufruft und die in
abgeleiteten Klassen überschrieben werden kann.
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class num_get : public locale::facet {
public:
typedef charT char_type;
typedef InputIterator iter_type;
explicit num_get(size_t refs = 0);
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, bool& v) const;
iter_type get(iter_type in, iter_type end, ios_base& ,
ios_base::iostate& err, long& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, unsigned short& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, unsigned int& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, unsigned long& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, float& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, double& v) const;

437
Die C++-Standardbibliothek

iter_type get(iter_type in, iter_type end, ios_base&,


ios_base::iostate& err, long double& v) const;
iter_type get(iter_type in, iter_type end, ios_base&,
ios_base::iostate& err, void*& v) const;
static locale::id id;
protected:
~num_get(); // virtual
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, bool& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, long& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, unsigned short& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, unsigned int& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, unsigned long& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, float& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, double& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, long double& v) const;
virtual iter_type do_get(iter_type, iter_type, ios_base&,
ios_base::iostate& err, void*& v) const;
};

num_put <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie numeric, zum Ausgeben
von numerischen Werten.
Enthält einen Satz von public-Methoden zum Ausgeben von numerischen Werten.
Jeder Methode entspricht eine virtuelle protected Version, die sie aufruft und die in
abgeleiteten Klassen überschrieben werden kann.
template <class charT, class OutputIterator =ostreambuf_iterator<charT> >
class num_put : public locale::facet {
public:
typedef charT char_type;
typedef OutputIterator iter_type;
explicit num_put(size_t refs = 0);
iter_type put(iter_type s, ios_base& f, char_type fill, bool v) const;
iter_type put(iter_type s, ios_base& f, char_type fill, long v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
unsigned long v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
double v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
long double v) const;
iter_type put(iter_type s, ios_base& f, char_type fill,

438
Die Hilfsklassen für die einzelnen Kategorien

void* v) const;
static locale::id id;
protected:
~num_put(); // virtual
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
bool v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
long v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
unsigned long) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
double v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
long double v) const;
virtual iter_type do_put(iter_type, ios_base&, char_type fill,
void* v) const;
};

numpunct <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie numeric, zur Zeichenset-
zung in numerischen Werten.
Enthält einen Satz von public-Methoden zur Zeichensetzung. Jeder Funktion ent-
spricht eine virtuelle protected Version, die sie aufruft und die in abgeleiteten Klas-
sen überschrieben werden kann.

template <class charT>


class numpunct : public locale::facet {
public:
typedef charT char_type;
typedef basic_string<charT> string_type;
explicit numpunct(size_t refs = 0);
char_type decimal_point() const;
char_type thousands_sep() const;
string grouping() const;
string_type truename() const;
string_type falsename() const;
static locale::id id;
protected:
~numpunct(); // virtual
virtual char_type do_decimal_point() const;
virtual char_type do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_truename() const; // für bool
virtual string_type do_falsename() const; // für bool
};

439
Die C++-Standardbibliothek

numpunct_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT>
class numpunct_byname : public numpunct<charT> {
public:
explicit numpunct_byname(const char*, size_t refs = 0);
protected:
~numpunct_byname(); // virtual
virtual char_type do_decimal_point() const;
virtual char_type do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_truename() const; // for bool
virtual string_type do_falsename() const; // for bool
};

time_base <locale>
Basisklasse zum Klassentemplate time_get, die einen Aufzählungstyp definiert, der
die wichtigsten Abfolgen von Datumsangaben spezifiziert.
class time_base {
public:
enum dateorder { no_order, // keine bevorzugte Reihenfolge
dmy, // Tag – Monat – Jahr
mdy, // Monat – Tag – Jahr
ymd, // Jahr – Monat – Tag
ydm // Jahr – Tag – Monat };
};

time_get <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie time, zum Einlesen von
Zeitangaben.
Enthält einen Satz von public-Methoden zum Einlesen von Zeitangaben. Jeder
Funktion entspricht eine virtuelle protected Version, die sie aufruft und die in abge-
leiteten Klassen überschrieben werden kann.
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class time_get : public locale::facet, public time_base {
public:
typedef charT char_type;
typedef InputIterator iter_type;
explicit time_get(size_t refs = 0);
dateorder date_order() const { return do_date_order(); }
iter_type get_time(iter_type s, iter_type end, ios_base& f,
ios_base::iostate& err, tm* t) const;
iter_type get_date(iter_type s, iter_type end, ios_base& f,
ios_base::iostate& err, tm* t) const;

440
Die Hilfsklassen für die einzelnen Kategorien

iter_type get_weekday(iter_type s, iter_type end, ios_base& f,


ios_base::iostate& err, tm* t) const;
iter_type get_monthname(iter_type s, iter_type end, ios_base& f,
ios_base::iostate& err, tm* t) const;
iter_type get_year(iter_type s, iter_type end, ios_base& f,
ios_base::iostate& err, tm* t\fP) const;
static locale::id id;
protected:
~time_get(); // virtual
virtual dateorder do_date_order() const;
virtual iter_type do_get_time(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_date(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_monthname(iter_type s, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_year(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
};

time_get_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT, class InputIterator = istreambuf_iterator<charT> >
class time_get_byname : public time_get<charT, InputIterator> {
public:
explicit time_get_byname(const char*, size_t refs = 0);
protected:
~time_get_byname(); // virtual
virtual dateorder do_date_order() const;
virtual iter_type do_get_time(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_date(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_weekday(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_monthname(iter_type s,iter_type end,ios_base&,
ios_base::iostate& err, tm* t) const;
virtual iter_type do_get_year(iter_type s, iter_type end, ios_base&,
ios_base::iostate& err, tm* t) const;
};

441
Die C++-Standardbibliothek

time_put <locale>
Klassentemplate zur Erzeugung von Facetten der Kategorie time, zur Ausgabe von
Zeitangaben.
Enthält einen Satz von public-Methoden zur Ausgabe von Zeitangaben. Jeder
Funktion entspricht eine virtuelle protected Version, die sie aufruft und die in abge-
leiteten Klassen überschrieben werden kann.
template <class charT, class OutputIterator =ostreambuf_iterator<charT> >
class time_put : public locale::facet {
public:
typedef charT char_type;
typedef OutputIterator iter_type;
explicit time_put(size_t refs = 0);
iter_type put(iter_type s, ios_base& f, char_type fill, const tm* tmb,
const charT* pattern, const charT* pat_end) const;
iter_type put(iter_type s, ios_base& f, char_type fill,
const tm* tmb, char format, char modifier = 0) const;
static locale::id id;
protected:
~time_put(); // virtual
virtual iter_type do_put(iter_type s,ios_base&,char_type,const tm* t,
char format, char modifier) const;
};

time_put_byname <locale>
Bietet die Möglichkeit, eine Facette, passend zu einer durch ihren Namen spezifi-
zierten locale-Einstellung, zu erzeugen. Dem Konstruktor wird dazu der Name der
locale-Einstellung übergeben.
template <class charT, class OutputIterator =ostreambuf_iterator<charT> >
class time_put_byname : public time_put<charT, OutputIterator> {
public:
explicit time_put_byname(const char*, size_t refs = 0);
protected:
~time_put_byname(); // virtual
virtual iter_type do_put(iter_type s,ios_base&,char_type,const tm* t,
char format, char modifier) const;
};

442
complex

Die numerischen Klassen

complex
aus <complex>

Beschreibung
Das Template complex implementiert eine Repräsentation der komplexen Zahlen sowie die auf
ihnen definierten Operationen.

Anwendung
Die Klasse complex selbst definiert lediglich die Konstruktoren zum Erzeugen von
komplexen Objekten und überladene Versionen der arithmetischen Operatoren.
complex<float> c(12.3, 0.5);
Die Klasse selbst definiert zwar nur die arithmetischen Operatoren, aber global
sind weitere Funktionen zur Arbeit mit complex-Objekten definiert:
● Überladene Formen der mathematischen C-Funktionen.
● Überladene Formen der Vergleichsoperatoren.
● Überladene Formen der Operatoren zur Ein- und Ausgabe.
● Spezielle Funktionen für komplexe Zahlen (real(), imag(), abs(), arg(),
norm(), conj() und polar()).
Ganzzahlen oder Gleitkommawerte können als komplexe Zahlen dargestellt wer-
den, deren Realteil der Ganzzahl/Gleitkommazahl entspricht und deren Imaginär-
teil gleich Null ist.
Für die Datentypen float, double und long double sind bereits entsprechende Tem-
plate-Instanzen spezialisiert.

Referenz
template<class T>
class complex {
public:
typedef T value_type;

complex(const T& re = T(), const T& im = T());


complex(const complex&);
template<class X> complex(const complex<X>&);

443
Die C++-Standardbibliothek

T real() const;
T imag() const;

complex<T>& operator= (const T&);


complex<T>& operator+=(const T&);
complex<T>& operator-=(const T&);
complex<T>& operator*=(const T&);
complex<T>& operator/=(const T&);

complex& operator=(const complex&);


template<class X> complex<T>& operator= (const complex<X>&);
template<class X> complex<T>& operator+=(const complex<X>&);
template<class X> complex<T>& operator-=(const complex<X>&);
template<class X> complex<T>& operator*=(const complex<X>&);
template<class X> complex<T>& operator/=(const complex<X>&);
};

valarray
aus <valarray>

Beschreibung
Das Template valarray dient dazu, geordnete Mengen zu repräsentieren. Durch die verschiede-
nen Möglichkeiten der Indizierung, die die Klasse zur Verfügung stellt, ist es möglich, die
Menge als Arrays oder Matrizen zu behandeln (bzw. entsprechende Klassen abzuleiten).
Ergänzt wird die Klasse valarray durch die global überladenen mathematischen
Funktionen und die Hilfsklassen zur Erzeugung von Teilmengen (slice,
slice_array, gslice, gslice_array, mask_array und indirect_array).

Anwendung
Zur Erzeugung eines valarray-Objekts spezialisiert man das Template für den
Datentyp der Mengenelemente und definiert ein Objekt der Klasse:
valarray<int> va(20);
Die Klasse valarray definiert – mit Ausnahme des Index-Operators [ ] – eine Reihe
von Funktionen zur Manipulation von Mengen, die stets alle Elemente der Klasse
betreffen.
Zusätzlich sind die wichtigsten Operatoren sowie die mathematischen Funktionen
für valarray<T> überladen, wobei die Operationen auf allen Elementen im valarray-
Objekt ausgeführt werden.
Der Index-Operator ist überladen, um entweder auf einzelne Elemente oder Teil-
mengen zuzugreifen.

444
valarray

for(int i = 0; i < 20; i++) {


va[i] = i; // Zugriff auf Einzelelemente
}
Mit Hilfe des Index-Operators [ ] lassen sich aus einem valarray-Objekt Teilmen-
gen herauslösen. Als Operand übergibt man dem Index-Operator dazu ein Objekt,
das die Indizes der valarray-Elemente spezifiziert, die zu der Teilmenge gehören sol-
len. Dies kann eine Instanz der Klassen slice, gslice, valarray<bool> oder valar-
ray<size_t> sein.
valarray<int> teil(5);
valarray<size_t> size(2);
size[0] = 3; size[1] = 4;
valarray<size_t> stride(2);
stride[0] = 5; stride[1] = 1;

teil = va[gslice(2,size,stride)];
cout << "\nTeilarray\n";
for(int i = 0; i < size[0]*size[1]; i++) {
cout << teil[i] << endl;
}
Wird der Operand auf ein konstantes valarray-Objekt angewendet, liefert er eine
Kopie der Teilmenge als neues valarray-Objekt zurück. Wird der Operand auf ein
nicht-konstantes valarray-Objekt angewendet, liefert er eine Referenz auf die Teil-
menge als Objekt des Typs slice_array, gslice_array, mask_array oder
indirect_array zurück. Alle Zugriffe auf diese Referenzen sind Zugriffe auf das Ori-
ginal-valarray.

Referenz
template<class T> class valarray {
public:
typedef T value_type;

// Konstruktoren:
valarray();
explicit valarray(size_t);
valarray(const T&, size_t);
valarray(const T*, size_t);
valarray(const valarray&);
valarray(const slice_array<T>&);
valarray(const gslice_array<T>&);
valarray(const mask_array<T>&);
valarray(const indirect_array<T>&);
~valarray();
// Zuweisung:
valarray<T>& operator=(const valarray<T>&);
valarray<T>& operator=(const T&);
valarray<T>& operator=(const slice_array<T>&);
valarray<T>& operator=(const gslice_array<T>&);

445
Die C++-Standardbibliothek

valarray<T>& operator=(const mask_array<T>&);


valarray<T>& operator=(const indirect_array<T>&);
// Zugriff auf Elemente:
T operator[](size_t) const;
T& operator[](size_t);
// Operationen auf Teilmengen:
valarray<T> operator[](slice) const;
slice_array<T> operator[](slice);
valarray<T> operator[](const gslice&) const;
gslice_array<T> operator[](const gslice&);
valarray<T> operator[](const valarray<bool>&) const;
mask_array<T> operator[](const valarray<bool>&);
valarray<T> operator[](const valarray<size_t>&) const;
indirect_array<T> operator[](const valarray<size_t>&);
// Sonstiges:
valarray<T> operator+() const;
valarray<T> operator-() const;
valarray<T> operator~() const;
valarray<T> operator!() const;
valarray<T>& operator*= (const T&);
valarray<T>& operator/= (const T&);
valarray<T>& operator%= (const T&);
valarray<T>& operator+= (const T&);
valarray<T>& operator-= (const T&);
valarray<T>& operator^= (const T&);
valarray<T>& operator&= (const T&);
valarray<T>& operator|= (const T&);
valarray<T>& operator<<=(const T&);
valarray<T>& operator>>=(const T&);
valarray<T>& operator*= (const valarray<T>&);
valarray<T>& operator/= (const valarray<T>&);
valarray<T>& operator%= (const valarray<T>&);
valarray<T>& operator+= (const valarray<T>&);
valarray<T>& operator-= (const valarray<T>&);
valarray<T>& operator^= (const valarray<T>&);
valarray<T>& operator|= (const valarray<T>&);
valarray<T>& operator&= (const valarray<T>&);
valarray<T>& operator<<=(const valarray<T>&);
valarray<T>& operator>>=(const valarray<T>&);

size_t size() const;


T sum() const;

valarray<T> shift (int) const;


valarray<T> cshift(int) const;
valarray<T> apply(T func(T)) const;
valarray<T> apply(T func(const T&)) const;
void resize(size_t sz, T c = T());
};

446
Teilmengen von valarray-Objekten

Verweise
Siehe Beispiel zu Header-Datei valarray

Teilmengen von valarray-Objekten


Beschreibung
Eine Reihe voin Hilfsklassen dienen dazu, eine bestimmte Menge von Elementen aus einem
valarray-Objekt auszuwählen. Instanzen dieser Klassen entsprechen quasi Aufzählungen von
Indizes auszuwählender Teilmengen und werden als Operand an den Index-Operator überge-
ben.

slice <valarray>
Eine Instanz der Klasse definiert jeweils eine Anzahl von Indizes, die einer Teil-
menge eines valarray-Objekts entsprechen. Die Indizes werden spezifiziert als
● Erster Index
● Anzahl der Indizes
● Abstand zwischen den Indizes

Beispiel
slice(3,5,2)
wählt aus einem Array die Elemente mit den Indizes
3, 5, 7, 9, 11
aus.
Um auf die Teilmenge zugreifen zu können, wird der Indexoperator [ ] der Klasse
valarray benutzt, beispielsweise:
valarr[slice(3,5,2)]

Referenz
class slice {
public:
slice();
slice(size_t, size_t, size_t);

size_t start() const;


size_t size() const;
size_t stride() const;
};

447
Die C++-Standardbibliothek

Verweise
Siehe Beispiel zu Header-Datei valarray

gslice <valarray>
Eine Instanz der Klasse definiert jeweils eine Anzahl von Indizes, die einer Teil-
menge eines valarray-Objekts entsprechen. Die Indizes werden spezifiziert als
● Erster Index (start)
● Anzahl der Indizes pro Dimension (size)
● Abstand zwischen den Indizes für jede Dimension (stride)
Die Dimension wird gegeben durch Anzahl der Elemente für size und stride.

Beispiel
Eine Instanz mit
start = 2;
size = {3,4};
stride = {5,1};
wählt beispielsweise aus einem valarray-Objekt die folgende 3x4-Matrix aus:
2, 3, 4, 5
7, 8, 9, 10
12, 13, 14, 15
Die Berechnung der Indizes k der ausgewählten Elemente im valarray-Objekt stellt
sich dar als
for(i=0;i<size[0];i++}
for(j=0;j<size[1];j++}
k = start + i*stride[i] + j*stride[j];
Um auf die Teilmenge zugreifen zu können, wird der Indexoperator [ ] der Klasse
valarray benutzt, beispielsweise:
valarray<size_t> size(2);
size[0] = 3; size[1] = 4;
valarray<size_t> stride(2);
stride[0] = 5; stride[1] = 1;

teil = va[gslice(2,size,stride)];

Referenz
class gslice {
public:
gslice();
gslice(size_t s, const valarray<size_t>& l, const valarray<size_t>& d);

size_t start() const;

448
Teilmengen von valarray-Objekten

valarray<size_t> size() const;


valarray<size_t> stride() const;
};

Teilmengen von valarray


Die Klassen slice_array, gslice_array, mask_array und indirect_array werden vom
Index-Operator von valarray als Rückgabetyp verwendet, wenn dieser auf ein
nicht-konstantes valarray-Objekt angewendet wird. Die zurückgelieferten Objekte
dienen dabei als Referenzen auf die mit Hilfe von slice, gslice, valarray<bool>
bzw. valarray<size_t> ausgewählten Teilmengen eines valarray-Objekts. Operatio-
nen auf diesen Teilmengen (beispielsweise die Anwendung der Methode fill(),
betreffen daher das originale valarray-Objekt. Die Klasse valarray definiert aber
auch Konstruktoren, um aus diesen Referenzobjekten eigene valarrays zu erzeugen.
Die Klassen sollen nicht explizit initialisiert werden, weswegen nur private-Kon-
struktoren definiert sind. Daneben sind die verschiedenen Formen von Zuweisungs-
operatoren und die Funktion fill() definiert, um die Elemente des valarray-
Objekts, auf die das xxx_array-Objekt verweist, zu verändern.

slice_array <vallarray>
Die Klasse dient dazu, eine – durch eine slice-Instanz definierte – Teilmenge eines
valarray-Objekts auszuwählen (Indexoperator [ ] der Klasse valarray), auf ihr zu
operieren oder sie in ein eigenständiges valarray-Objekt umzuwandeln (letzteres
mit Hilfe des entsprechenden Konstruktors der Klasse valarray).

Beispiel
valarr[slice(3,8,2)].fill(3);

Referenz
template <class T> class slice_array {
public:
typedef T value_type;

void operator= (const valarray<T>&) const;


void operator*= (const valarray<T>&) const;
void operator/= (const valarray<T>&) const;
void operator%= (const valarray<T>&) const;
void operator+= (const valarray<T>&) const;
void operator-= (const valarray<T>&) const;
void operator^= (const valarray<T>&) const;
void operator&= (const valarray<T>&) const;
void operator|= (const valarray<T>&) const;
void operator<<=(const valarray<T>&) const;
void operator>>=(const valarray<T>&) const;
void fill(const T&);

449
Die C++-Standardbibliothek

~slice_array();
private:
slice_array();
slice_array(const slice_array&);
slice_array& operator=(const slice_array&);
};

gslice_array <valarray>
Die Klasse dient dazu, eine – durch eine gslice-Instanz definierte – Teilmenge eines
valarray-Objekts auszuwählen (Indexoperator [ ] der Klasse valarray), auf ihr zu
operieren oder sie in ein eigenständiges valarray-Objekt umzuwandeln (letzteres
mit Hilfe des entsprechenden Konstruktors der Klasse valarray).
template <class T> class gslice_array {
public:
typedef T value_type;

void operator= (const valarray<T>&) const;


void operator*= (const valarray<T>&) const;
void operator/= (const valarray<T>&) const;
void operator%= (const valarray<T>&) const;
void operator+= (const valarray<T>&) const;
void operator-= (const valarray<T>&) const;
void operator^= (const valarray<T>&) const;
void operator&= (const valarray<T>&) const;
void operator|= (const valarray<T>&) const;
void operator<<=(const valarray<T>&) const;
void operator>>=(const valarray<T>&) const;
void fill(const T&);
~gslice_array();
private:
gslice_array();
gslice_array(const gslice_array&);
gslice_array& operator=(const gslice_array&);
};

mask_array <valarray>
Die Klasse dient dazu, eine – durch eine valarray<bool>-Instanz definierte – Teil-
menge eines valarray-Objekts auszuwählen (Indexoperator [ ] der Klasse valarray),
auf ihr zu operieren oder sie in ein eigenständiges valarray-Objekt umzuwandeln
(letzteres mit Hilfe des entsprechenden Konstruktors der Klasse valarray).
template <class T> class mask_array {
public:
typedef T value_type;

void operator= (const valarray<T>&) const;


void operator*= (const valarray<T>&) const;
void operator/= (const valarray<T>&) const;

450
Teilmengen von valarray-Objekten

void operator%= (const valarray<T>&) const;


void operator+= (const valarray<T>&) const;
void operator-= (const valarray<T>&) const;
void operator^= (const valarray<T>&) const;
void operator&= (const valarray<T>&) const;
void operator|= (const valarray<T>&) const;
void operator<<=(const valarray<T>&) const;
void operator>>=(const valarray<T>&) const;
void fill(const T&);
~mask_array();
private:
mask_array();
mask_array(const mask_array&);
mask_array& operator=(const mask_array&);
};

indirect_array <valarray>
Die Klasse dient dazu, eine – durch eine valarray<size_t>-Instanz definierte – Teil-
menge eines valarray-Objekts auszuwählen (Indexoperator [ ] der Klasse valarray),
auf ihr zu operieren oder sie in ein eigenständiges valarray-Objekt umzuwandeln
(letzteres mit Hilfe des entsprechenden Konstruktors der Klasse valarray).
template <class T> class indirect_array {
public:
typedef T value_type;

void operator= (const valarray<T>&) const;


void operator*= (const valarray<T>&) const;
void operator/= (const valarray<T>&) const;
void operator%= (const valarray<T>&) const;
void operator+= (const valarray<T>&) const;
void operator-= (const valarray<T>&) const;
void operator^= (const valarray<T>&) const;
void operator&= (const valarray<T>&) const;
void operator|= (const valarray<T>&) const;
void operator<<=(const valarray<T>&) const;
void operator>>=(const valarray<T>&) const;
void fill(const T&);
~indirect_array();
private:
indirect_array();
indirect_array(const indirect_array&);
indirect_array& operator=(const indirect_array&);
};

451
Die C++-Standardbibliothek

numeric_limits
aus <limits>

Beschreibung
Die Klasse numeric_limits kapselt die Informationen über die implementierungsspezifische
Repräsentation der numerischen Datentypen. Verschiedene Elemente der Klasse sind nur für
bestimmte Datentypen sinnvoll zu definieren. Datenelemente, die nicht zur Charakterisierung
eines Datentyps beitragen, werden auf Null oder false gesetzt. Außer des Templates sind in der
Laufzeitbibliothek auch Spezialisierungen für die elementaren Datentypen definiert.

Referenz
template<class T> class numeric_limits {
public:
static const bool is_specialized = false;
static T min() throw();
static T max() throw();
static const int digits = 0;
static const int digits10 = 0;
static const bool is_signed = false;
static const bool is_integer = false;
static const bool is_exact = false;
static const int radix = 0;
static T epsilon() throw();
static T round_error() throw();

static const int min_exponent = 0;


static const int min_exponent10 = 0;
static const int max_exponent = 0;
static const int max_exponent10 = 0;

static const bool has_infinity = false;


static const bool has_quiet_NaN = false;
static const bool has_signaling_NaN = false;
static const bool has_denorm = false;
static const bool has_denorm_loss = false;
static T infinity() throw();
static T quiet_NaN() throw();
static T signaling_NaN() throw();
static T denorm_min() throw();

static const bool is_iec559 = false;


static const bool is_bounded = false;
static const bool is_modulo = false;

static const bool traps = false;


static const bool tinyness_before = false;
static const float_round_style round_style = round_toward_zero;
};

452
exception

Klassen und Funktionen zur


Exception-Behandlung

exception
aus <exception>

Beschreibung
Basisklasse für die Exception-Objekte, die von der Sprache und den Komponenten der C++-
Standardbibliotheken ausgelöst werden (oder zur Bequemlichkeit des Programmierers vordefi-
niert sind). Direkt von ihr abgeleitet sind die von der Sprache verwendeten Exceptions (bad_...)
sowie die Klassen logic_error (logische Fehler) und runtime_error (Laufzeitfehler), von
denen wiederum die restlichen Exception-Klassen abgeleitet sind.

Anwendung
Enthält neben Konstruktor, Destruktor noch einen Kopierkonstruktor und entspre-
chend eine eigene Version des Zuweisungsoperators, sowie eine Methode zum Aus-
geben eines Meldungsstrings.
Da alle Elemente der Klasse mit throw() deklariert sind, kann die Klasse selbst keine
Exceptions auslösen.
Von der Klasse exception selbst werden üblicherweise keine Exception-Objekte
gebildet, sie dient lediglich als Basisklasse.

Referenz
class exception {
public:
exception() throw();
exception(const exception&) throw();
exception& operator=(const exception&) throw();
virtual ~exception() throw();
virtual const char* what() const throw();
};

453
Die C++-Standardbibliothek

Abgeleitete Exception-Klassen
aus <exception>, <stdexcept> und <typeinfo>
Klassentyp für Exceptions, die von den Methoden der Laufzeitbibliothek im Falle
eines Fehlers bei der Speicherreservierung ausgelöst werden.
class bad_alloc : public exception {
public:
bad_alloc() throw();
bad_alloc(const bad_alloc&) throw();
bad_alloc& operator=(const bad_alloc&) throw();
virtual ~bad_alloc() throw();
virtual const char* what() const throw();
};
Klassentyp für Exceptions, die im Falle einer gescheiterten Typumwandlung mittels
dynamic_cast ausgelöst werden.
class bad_cast : public exception {
public:
bad_cast() throw();
bad_cast(const bad_cast&) throw();
bad_cast& operator=(const bad_cast&) throw();
virtual ~bad_cast() throw();
virtual const char* what() const throw();
};
Klassentyp für Exceptions, die bei Fehlern in der Exception-Behandlung (Auslö-
sung einer Exception in einer Klasse, für die die Exception nicht deklariert ist, Auf-
treten einer nicht behandelten Exception, etc.) ausgelöst werden.
class bad_exception : public exception {
public:
bad_exception() throw();
bad_exception(const bad_exception&) throw();
bad_exception& operator=(const bad_exception&) throw();
virtual ~bad_exception() throw();
virtual const char* what() const throw();
};
Klassentyp für Exceptions, die bei Auftreten eines Null-Zeigers in einem typeid-
Ausdruck ausgelöst werden.
class bad_typeid : public exception {
public:
bad_typeid() throw();
bad_typeid(const bad_typeid&) throw();
bad_typeid& operator=(const bad_typeid&) throw();
virtual ~bad_typeid() throw();
virtual const char* what() const throw();
};

454
Abgeleitete Exception-Klassen

Klassentyp für Exceptions, die bei Auftreten von unzulässigen Werten ausgelöst
werden.
class domain_error : public logic_error {
public:
domain_error(const string& what_arg);
};
Klassentyp für Exceptions, die bei Übergabe unzulässiger Argumente ausgelöst wer-
den.
class invalid_argument : public logic_error {
public:
invalid_argument(const string& what_arg);
};
Klassentyp für Exceptions, die ausgelöst werden, wenn die zulässige Größe von
Datenstrukturen überschritten wird.
class length_error : public logic_error {
public:
length_error(const string& what_arg);
};
Klassentyp für Exceptions, die bei Auftreten logischer Fehler – also Fehlern, die
möglicherweise noch vor der Programmausführung aufgespürt werden können –
ausgelöst werden.
class logic_error : public exception {
public:
logic_error(const string& what_arg);
};
Klassentyp für Exceptions, die ausgelöst werden, wenn ein übergebenes Argument
nicht im vorgesehenen Wertebereich liegt.
class out_of_range : public logic_error {
public:
out_of_range(const string& what_arg);
};
Klassentyp für Exceptions, die bei Überlauf arithmetischer Variablen ausgelöst
werden.
class overflow_error : public runtime_error {
public:
overflow_error(const string& what_arg);
};
Klassentyp für Exceptions, die bei Verletzung von Gültigkeitsbereichen ausgelöst
werden.
class range_error : public runtime_error {
public:
range_error(const string& what_arg);
};

455
Die C++-Standardbibliothek

Klassentyp für Exceptions, die bei Auftreten von Laufzeitfehlern – also Fehlern, die
meist erst während der Programmausführung aufgespürt werden können – ausge-
löst werden.
class runtime_error : public exception {
public:
runtime_error(const string& what_arg);
};
Klassentyp für Exceptions, die bei Unterlauf arithmetischer Variablen ausgelöst
werden.
class underflow_error : public runtime_error {
public:
underflow_error(const string& what_arg);
};

Funktionen zur Exception-Behandlung


set_new_handler() <new>
Richtet die Funktion ein, die vom Operator new zur Fehlerbehandlung aufgerufen
wird. Dazu wird ein Zeiger auf die Fehlerbehandlungsfunktion, der vom Typ
new_handler (typedef void (*new_handler)() )
sein muß, übergeben.
new_handler set_new_handler(new_handler new_p) throw();
● Rückgabe: Zeiger auf die alte Fehlerbehandlungsfunktion.

set_terminate() <exception>
Richtet die Funktion ein, die bei vorzeitigen Programmabbrüchen, z. B. infolge
unbehandelter Exceptions aufgerufen wird. Dazu wird ein Zeiger auf die Pro-
grammabbruchfunktion, der vom Typ
terminate_handler (typedef void (*terminate_handler)() )
sein muß, übergeben.
terminate_handler set_terminate(terminate_handler t_func) throw();
● Rückgabe: Zeiger auf die alte Programmabbruchfunktion.

set_unexpected() <exception>
Richtet die Funktion ein, die aufgerufen wird, wenn innerhalb einer Funktion eine
Exception ausgelöst wird, für die die Funktion nicht deklariert ist. Die eingerichtete
Funktion muß entweder

456
Funktionen zur Exception-Behandlung

● eine Exception auslösen, für die die Funktion deklariert ist,


● eine bad_exception-Exception auslösen,
● die Funktion terminate() aufrufen,
● abort() oder exit() aufrufen.
Zur Einrichtung wird ein Zeiger auf die Fehlerbehandlungsfunktion, der vom Typ
unexpected_handler(typedef void (*unexpected_handler)() )
sein muß, übergeben.
unexpected_handler set_unexpected(unexpected_handler unexp_func);
● Rückgabe: Zeiger auf die alte Funktion.

terminate() <exception>
Die Funktion terminate() wird bei Auftreten eines Fehlers zum vorzeitigen Pro-
grammabbruch aufgerufen, beispielsweise wenn keine Behandlungsfunktion zu
einer ausgelösten Exception gefunden wird (meist also von unexpected() ). Die
Funktion terminate() ruft ihrerseits die von set_terminate() eingerichtete Funktion
zum Programmabbruch auf.
void terminate();

uncaught_exception() <exception>
Zeigt an, daß eine Exception ausgelöst wurde, zu der bislang kein Handler gefun-
den wurde. Kann beispielsweise in Destruktoren verwendet werden.
bool uncaught_exception();
● Rückgabe: true, wenn eine bisher unbehandelte Exception vorliegt.

unexpected() <exception>
Die Funktion unexpected() wird aufgerufen, wenn in einer Funktion eine Exception
ausgelöst wird, für die die Funktion nicht deklariert ist. Die Funktion unexpected()
ruft ihrerseits die von set_unexpected() eingerichtete Funktion zur Behandlung auf.
void unexpected();

457
Die C++-Standardbibliothek

Laufzeittypidentifizierung

type_info
aus <typeinfo>

Beschreibung
Die Tatsache, daß jede Instanz einer abgeleiteten Klasse in C++ auch als Instanz ihrer Basis-
klassen aufgefaßt werden kann, erweitert einerseits die Möglichkeiten der dynamischen
Typumwandlung, erschwert allerdings auch die Übersicht über die aktuellen Datentypen von
Zeigern und Referenzen auf Klasseninstanzen. Die Klasse type_info bietet die Möglichkeit, zur
Laufzeit des Programms Informationen zum Datentyp eines Objekts abzufragen.

Anwendung
Die Klasse type_info definiert nur private Konstruktoren. Sie kann daher nicht
explizit initialisiert werden. Statt dessen wird die Klasse in Zusammenhang mit
dem typeid-Operator benutzt, der Referenzen der Klasse erzeugt.

Referenz
class type_info {
public:
virtual ~type_info();
bool operator==(const type_info& rhs) const;
bool operator!=(const type_info& rhs) const;
bool before(const type_info& rhs) const;
const char* name() const;
private:
type_info(const type_info& rhs);
type_info& operator=(const type_info& rhs);
};
}

458
Die Struktur pair

Utilities

Die Struktur pair


aus <utility>
Das Klassentemplate repräsentiert ein Paar von Objekten unterschiedlichen Daten-
typs. Neben dem Konstruktor kann auch das globale Funktionentemplate
make_pair() aufgerufen werden.
template <class T1, class T2>
struct pair {
typedef T1 first_type;
typedef T2 second_type;

T1 first;
T2 second;
pair();
pair(const T1& x, const T2& y);
template<class U, class V> pair(const pair<U, V> &p);
};
template <class T1, class T2>
pair<T1, T2> make_pair(const T1& x, const T2& y);

Funktionsobjekte
aus <functional>

Beschreibung
Die Implementierung generischer Funktionen beruht oftmals auf der Übergabe von Funktionen
als Parameter (vergleiche qsort() ). Die STL erweitert dieses Konzept, indem sie Funktionen in
Klassen kapselt. Allen diesen Klassen gemeinsam ist, daß der ()-Operator für sie überladen
wurde, damit die Instanzen der Klasse (die Funktionsobjekte) wie Funktionen aufgerufen wer-
den können.
Funktionsobjekte sind mächtiger als Funktionen, da sie auf die internen Daten und
Methoden ihrer Klasse zurückgreifen können. Zudem sind alle Funktionsobjekte
der STL als Templates implementiert, um mit beliebigen Datentypen arbeiten zu
können.
Die STL unterscheidet
● Arithmetische Funktionsobjekte, die eine arithmetische Operation durchfüh-
ren (divides, etc.), und

459
Die C++-Standardbibliothek

● Prädikate, die einen Vergleich durchführen (equal_to, etc.), bool als Ergebnis-
typ haben und in den Algorithmen der STL häufig verwendet werden, um eine
Bedingung zu definieren, die die Elemente, auf denen die Algorithmenfunktion
operiert, erfüllen müssen.
● Negatoren, die ein Prädikat negieren.
● Binder, die es erlauben ein binäres Funktionsobjekt (zwei Argumente) wie ein
Funktionsobjekt mit einem Argument einzusetzen.
● Adapter, die es ermöglichen Methoden oder Zeiger auf Funktionen als Argu-
mente an Algorithmen zu übergeben.

Basisstrukturen
Abgeleitet sind die Funktionsobjekte von den Strukturen unary_function und
binary_function, je nachdem, ob ihr ()-Operator ein oder zwei Argumente erwartet.
template <class Arg, class Result>
struct unary_function {
typedef Arg argument_type;
typedef Result result_type;
};
template <class Arg1, class Arg2, class Result>
struct binary_function {
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};

Arithmetische Funktionsobjekte
Alle Funktionsobjekte definieren den ()-Operator um wie Funktionen aufgerufen
werden zu können.
template <class T> struct divides : public binary_function<T,T,T>
T operator()(const T& x, const T& y) const;
template <class T> struct minus : public binary_function<T,T,T>
T operator()(const T& x, const T& y) const;
template <class T> struct modulus : public binary_function<T,T,T>
T operator()(const T& x, const T& y) const;
template <class T> struct multiplies : public binary_function<T,T,T>
T operator()(const T& x, const T& y) const;
template <class T> struct negate : public unary_function<T,T>
T operator()(const T& x) const;
template <class T> struct plus : public binary_function<T,T,T>
T operator()(const T& x, const T& y) const;

460
Funktionsobjekte

Prädikate
Auch die vordefinierten Prädikate definieren nur den ()-Operator.
template <class T> struct equal_to : public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct greater : public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct greater_equal:public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct less : public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct less_equal : public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct logical_and : public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct logical_or: public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;
template <class T> struct logical_not: public unary_function<T,bool>
bool operator()(const T& x) const;
template <class T> struct not_equal_to: public binary_function<T,T,bool>
bool operator()(const T& x, const T& y) const;

Negatoren
template <class Predicate>
class unary_negate
: public unary_function<Predicate::argument_type,bool> {
public:
explicit unary_negate(const Predicate& pred);
bool operator()(const argument_type& x) const;
};
Funktionsklasse zur Negation eines Aussageobjekts. Der Template-Parameter Pre-
dicate bezeichnet ein unäres Funktionsobjekt, dessen Aussage negiert werden soll.
Üblicherweise verwendet man das globale Funktionentemplate not1() zur Bildung
eines unary_negate-Objekts.
template <class Predicate>
class binary_negate
: public binary_function<Predicate::first_argument_type,
Predicate::second_argument_type, bool> {
public:
explicit binary_negate(const Predicate& pred);
bool operator()(const first_argument_type& x,
const second_argument_type& y) const;
};
Funktionsklasse zur Negation eines Aussageobjekts. Der Template-Parameter
bezeichnet ein binäres Funktionsobjekt, dessen Aussage negiert werden soll. Übli-
cherweise verwendet man das globale Funktionentemplate not2() zur Bildung eines
binary_negate-Objekts.

461
Die C++-Standardbibliothek

template <class Predicate>


unary_negate<Predicate> not1(const Predicate& pred);
template <class Predicate>
binary_negate<Predicate> not2(const Predicate& pred);
Die Funktion not1() übernimmt eine unäre Aussage, die Funktion not2() eine
binäre Aussage. Beide liefern die negierten Aussagen als Instanzen der Template-
Klassen unary_negate bzw. binary_negate zurück.

Binder
template <class Operation>
class binder1st
: public unary_function<Operation::second_argument_type,
Operation::result_type> {
protected:
Operation op;
Operation::first_argument_type value;
public:
binder1st(const Operation& x,const Operation::first_argument_type& y);
result_type operator()(const argument_type& x) const;
};
Wandelt ein binäres Funktionsobjekt in ein unäres Funktionsobjekt, indem dem
ersten Argument ein fester Wert zugewiesen wird. Üblicherweise verwendet man
das globale Funktionentemplate bind1st() zur Bildung eines binder1st-Objekts.
template <class Operation>
class binder2nd
: public unary_function<Operation::first_argument_type,
Operation::result_type> {
protected:
Operation op;
Operation::second_argument_type value;
public:
binder2nd(const Operation& x,const Operation::second_argument_type& y);
result_type operator()(const argument_type& x) const;
};
Wandelt ein binäres Funktionsobjekt in ein unäres Funktionsobjekt, indem dem
zweiten Argument ein fester Wert zugewiesen wird. Üblicherweise verwendet man
das globale Funktionentemplate bind2nd() zur Bildung eines binder2nd-Objekts.
template <class Operation, class T>
binder1st<Operation> bind1st(const Operation& op, const T& x);
template <class Operation, class T>
binder2nd<Operation> bind2nd(const Operation& op, const T& x);
Beide Funktionen dienen dazu, aus einem Funktionsobjekt mit zwei Argumenten
ein Funktionsobjekt mit einem Objekt zu machen. Dazu wird ein Argument an
einen konstanten Wert »gebunden«. bind1st() bindet das 1. Argument, bind2nd()
das zweite.

462
Funktionsobjekte

Adapter
Um Funktionszeiger an Binder übergeben zu können, stellt die C++-Bibliothek die
Adapterklassen pointer_to_unary_function und pointer_to_binary_function zur Ver-
fügung:
template <class Arg, class Result>
class pointer_to_unary_function
: public unary_function<Arg,Result>
{
public:
explicit pointer_to_unary_function(Result (*f)(Arg));
Result operator()(Arg x) const;
};
template <class Arg1, class Arg2, class Result>
class pointer_to_binary_function
: public binary_function<Arg1,Arg2,Result>
{
public:
explicit pointer_to_binary_function(Result (*f)(Arg1,Arg2));
Result operator()(Arg1 x, Arg2 y) const;
};
sowie die überladene globale Funktion ptr_fun():
template <class Arg, class Result>
pointer_to_unary_function<Arg, Result>
ptr_fun(Result (*f)(Arg));
template <class Arg1, class Arg2, class Result>
pointer_to_binary_function<Arg1,Arg2,Result>
ptr_fun(Result (*f)(Arg1, Arg2));
Um auch Methoden als Argumente an Funktionsobjekt-Parameter von Algorithmen
übergeben zu können (Methode muß über Instanz aufgerufen werden), sind die
Klassen mem_fun_t, mem_fun1_t, mem_fun_ref_t und mem_fun1_ref_t für Methoden ohne
und mit einem Argument definiert
template <class S, class T> class mem_fun_t
: public unary_function<T*, S> {
public:
explicit mem_fun_t(S (T::*p)());
S operator()(T* p);
};
template <class S, class T, class A> class mem_fun1_t
: public binary_function<T*, A, S> {
public:
explicit mem_fun1_t(S (T::*p)(A));
S operator()(T* p, A x);
};
template <class S, class T> class mem_fun_ref_t
: public unary_function<T, S> {
public:

463
Die C++-Standardbibliothek

explicit mem_fun_ref_t(S (T::*p)());


S operator()(T& p);
};
template <class S, class T, class A> class mem_fun1_ref_t
: public binary_function<T, A, S> {
public:
explicit mem_fun1_ref_t(S (T::*p)(A));
S operator()(T& p, A x);
};
sowie die globalen Funktionen mem_fun(), mem_fun1(), mem_fun_ref() und
mem_fun1_ref(), denen man einen Methodenzeiger (bzw. Methodenreferenz) als
Argument übergeben kann und deren Rückgabewert als Argument an einen Funkti-
onsobjekt-Parameter weitergegeben werden kann.
template<class S, class T> mem_fun_t<S,T>
mem_fun(S (T::*f)());
template<class S, class T, class A> mem_fun1_t<S,T,A>
mem_fun1(S (T::*f)(A));
template<class S, class T> mem_fun_ref_t<S,T>
mem_fun_ref(S (T::*f)());
template<class S, class T, class A> mem_fun1_ref_t<S,T,A>
mem_fun1_ref(S (T::*f)(A));

Speicherallokation

allocator
aus <memory>

Beschreibung
Die Klasse allocator definiert Methoden zur Anforderung und Verwaltung physikalischen
Speichers. Eine Instanz der Klasse übernimmt damit die Aufgabe eines Speichermanager. Die
von ANSI vorgesehene Implementierung beruht auf der üblichen Verwendung der Operatoren
new und delete.
Die STL-Container verwenden Allokatoren für die Speicheranforderung, d. h., die Methoden der
Container greifen intern zur Speicheranforderung und -verwaltung auf die Methoden des Allo-
katorobjekts zurück. Standardmäßig verwenden die Container eine Instanz der Klasse alloca-
tor, die als Vorgabeargument für den entsprechenden Template-Parameter vorgesehen ist.
Durch Implementierung und Übergabe eigener Allokatoren mit gleicher Schnittstelle kann ein
Programmierer die Speicherverwaltung eines Containers an verschiedene Speichermodelle
(DOS, 16-Bit-Windows) anpassen.

464
auto_ptr

Referenz
template <class T> class allocator {
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U> struct rebind { typedef allocator<U> other; };
allocator() throw();
allocator(const allocator&) throw();
template <class U> allocator(const allocator<U>&) throw();
~allocator() throw();
pointer address(reference x) const;
const_pointer address(const_reference x) const;
pointer allocate(
size_type, typename allocator<void>::const_pointer hint = 0);
void deallocate(pointer p, size_type n);
size_type max_size() const throw();
void construct(pointer p, const T& val);
void destroy(pointer p);
};

auto_ptr
aus <memory>
Dient dazu, den Speicherbereich eines mit new eingerichteten Objekts automatisch
freizugeben, wenn der Zeiger auf den Speicherbereich gelöscht wird (zum Beispiel
durch Verlassen seines Gültigkeitsbereichs).
template<class X> class auto_ptr {
public:
typedef X element_type;
explicit auto_ptr(X* p =0) throw();
auto_ptr(const auto_ptr&) throw();
template<class Y> auto_ptr(const auto_ptr<Y>&) throw();
auto_ptr& operator=(const auto_ptr&) throw();
template<class Y> auto_ptr& operator=(const auto_ptr<Y>&) throw();
~auto_ptr();
X& operator*() const throw();
X* operator->() const throw();
X* get() const throw();
X* release() const throw();
};

465
Die C++-Standardbibliothek

Funktionen und Iteratoren


raw_storage_iterator <memory>
Dient dazu, Objekte in nicht-initialisierten Speicherbereichen abzulegen.
template <class OutputIterator, class T>
class raw_storage_iterator
: public iterator<output_iterator_tag,void,void> {
public:
explicit raw_storage_iterator(OutputIterator x);
raw_storage_iterator<OutputIterator,T>& operator*();
raw_storage_iterator<OutputIterator,T>& operator=(const T& element);
raw_storage_iterator<OutputIterator,T>& operator++();
raw_storage_iterator<OutputIterator,T> operator++(int);
};

get_temporary_buffer() <memory>
Liefert die Pufferadresse und die Kapazität des Puffers in Einheiten von T als
Instanz der Klasse pair zurück.
template <class T> pair<T*, ptrdiff_t> get_temporary_buffer(ptrdiff_t n);

return_temporary_buffer() <memory>
Gibt den Puffer zurück, auf den ptr verweist und der mit get_temporary_buffer()
allokiert wurde.
template <class T> void return_temporary_buffer(T* ptr);

uninitialized_... <memory>
Die Funktion uninitialized_copy() ruft new in einer Schleife auf, um den Bereich
von result bis result + last mit den Werten aus [first, last) zu initialisieren.
Die Funktion uninitialized_fill() ruft new in einer Schleife auf, um den Bereich
von first bis last mit wert zu initialisieren.
Die Funktion uninitialized_fill_n() ruft new in einer Schleife auf, um den Bereich
von first bis first+n mit wert zu initialisieren.
template <class InIter, class FWIter>
FWIter uninitialized_copy(InIter first, InIter last, FWIter result);
template <class FWIter, class T>
void uninitialized_fill(FWIter first,FWIter last, const T& wert);
template <class FWIter, class Size, class T>
void uninitialized_fill_n(FWIter first, Size n, const T& wert);

466
Index
Index

- (Vorzeichen) 101
!
! 107
- 102
-- 103
!= 106
# 224
## 224
#define 96, 220
#elif 222
#else 223
#endif 223
#error 225
#if 222
#ifdef 223
#ifndef 223
#include 219
#line 225
#pragma 226
% 102
& 113
& (Adresse) 126
& (Referenzen) 87
&& 107
( ) (Parameterliste) 145
() (Typumwandlung) 120
* 102
* (Zeiger-Deklaration) 81
* (Zeiger-Dereferenzierung) 83, 109
+ 102
+ (Vorzeichen) 101
++ 103
, 127
. 110
.* 111
... 157
/ 102
: 112
::* (Zeiger auf Klassenelemente) 86
< 106
<< 115
<< (Streamoperator) 116
<= 106

468
Index

<x>= 105, 113


= 104
== 106
-> 111
> 106
->* 111
>= 106
>> 115
>> (Streamoperator) 116
? 126
[ ] (Array-Deklaration) 67
[ ] (Array-Indizierung) 67, 110
^ 114
{} 23
| 114
|| 107
~ 115
A
Abgeschlossenheit 167
Abstrakte Klassen 201
Abstrakte Methoden 201
Adapter für Funktionsobjekte 463
advance() 392
Algorithmen 392
allocator 464
ANSI-Standard 15
Anweisungen 22
Arrays 67
– Initialisierung 68
– mehrdimensionale Arrays 70
– von Klassenobjekten 188
– Zeichenketten 72
– Zugriff auf Elemente 69
assert() 247
Assoziativität 128
Aufbau von Programmen 17
Aufzählungstypen 66
– Speicherbelegung 67
auto 55
auto_ptr 465
B
back_insert_iterator 386
bad_alloc 454

469
Index

bad_cast 454
bad_typeid 454
basic_filebuf 415
basic_fstream 419
basic_ifstream 417
basic_ios 404
basic_iostream 411
basic_istream 407
basic_istringstream 413
basic_ofstream 418
basic_ostream 409
basic_ostringstream 414
basic_streambuf 405
basic_string 237, 421
basic_stringbuf 411
basic_stringstream 415
Basisklassen 165
– direkte 196
– indirekte 197
– polymorphe 121
– virtuelle 205
– Zugriff auf verdeckte Elemente 63
Basisklassenobjekte
– einrichten 195
– Zuweisung abgeleiteter Objekte 105
Basisklassenzeiger 86, 202
– in Zeiger auf abgeleitete Objekte umwandeln 121
Bedingte Kompilierung 222
Bedingungsoperator 126
Bezeichner 17, 46
Bibliotheken
– Standardbibliotheken 29
binary_function 460
binary_negate 461
bind1st() 462
bind2nd() 462
Binder für Funktionsobjekte 462
binder1st 462
binder2nd 462
Bindung, späte 199
Bitfelder
– als bitset-Container 332, 360
– als Strukturen 77

470
Index

bitset 332, 360


Blockbereich 58
bool 50
break 142
C
C/C++
– Alternative Zeichen 45
– ANSI-Standard 15
– Aufbau von Programmen 17
– Ein- und Ausgabe 31
– Groß- und Kleinschreibung 17
– Leistungsmerkmale 15
– Schlüsselwörter 44
– Schreibkonventionen 17
– Symbole 44
– Zeichensatz 41
case 135
Cast-Operator 93, 120
catch 232
cerr 242
char 50
char_traits 420
cin 242
class 165
class (Template-Parameter) 208
clog 242
codecvt 431
codecvt_base 430
codecvt_byname 432
collate 432
collate_byname 433
Compiler 34
– Bedingte Kompilierung 222
– Borland C++ 36
– C++-Builder 37
– GNU-Compiler 35
– Standardkonvertierungen 90
– Visual C++ 38
complex 443
const (Datenelemente) 170
const (Methoden) 160, 175
const (Parameter) 89
const (Variablen) 55, 98

471
Index

const (Zeiger) 85
const_cast 121
Container 357
– allgemeine Eigenschaften 358
– assoziative Container 359
– bitset 360
– deque 362
– list 365
– map 367
– multimap 367
– multiset 375
– priority_queue 372
– queue 373
– sequentielle Container 358
– set 375
– stack 378
– vector 379
continue 142
cout 242
ctype 429
ctype_base 428
ctype_byname 430
D
Dateibereich 58
Datentypen 48
– arithmetische 49
– Arrays 67
– Aufzählungstypen 66
– Codierung 48
– elementare 50
– integrale 49
– Klassen 164
– Konvertierungen durch Compiler 90
– Literale 94
– skalare 49
– Speicherbelegung 49
– Strukturen 74
– Templates 207
– Unions 79
– Wertebereich 49
– zusammengesetzte 65
default 136
defined 223

472
Index

Definition 47
Deklaration 47
Dekrement 103
delete 117
deque 362
Dereferenzierung 83
Destruktor 186
– bei Vererbung 201
Diagnoseklassen 453
Diagnosemeldungen 225
difftime() 261
distance() 392
divides 460
do 141
domain_error 455
double 51
dynamic_cast 121, 204
E
Ein- und Ausgabe 31, 239
– cerr 242
– cin 242
– clog 242
– cout 242
– Fehlerbehandlung in C++ 245
– FILE 240
– formatiert in C 239
– formatiert in C++ 239
– Formatierung in C++ 242
– Funktionen in C 240
– Manipulatoren in C++ 244
– Pufferung 246
– stderr 240
– stdin 240
– stdout 240
– Streams in C 240
– Streams in C++ 242
– unformatiert in C 239
– unformatiert in C++ 239
Einbettung
– Initialisierung eingebetteter Objekte 171
– versus Vererbung 191
Elemente in Programme einführen 46
else 133

473
Index

endl 338
enum 66
equal_to 461
errno 249
Escape-Sequenzen 42
exception 453
Exceptions 226
– abfangen 232
– auslösen 230
– eigene Exceptionklassen definieren 229
– Funktionsdeklaration mit throw 231
– Handlerbereich festlegen 233
– Schema der Exception-Behandlung 228
– verwandte Funktionen 233
– Vor- und Nachteile 226
exit() 142, 254
explicit 184
export 208
extern 57, 146, 159
F
false 50
FILE 240
Flags 77, 360
Fließkommazahlen 52
float 51
for 138
friend 180
Friends 180
– in Templates 210
front_insert_iterator 386
Function Overhead 156
Funktionen 143
– call by reference 151
– call by value 151
– const-Parameter 152
– der C-Laufzeitbibliotheken 264
– Exceptions auslösen 147, 231
– Function Overhead 156
– globale Variablen 149
– inline-Funktionen 147, 158
– main() 147
– mit beliebig vielen Argumenten 157
– ohne Rückgabewert 146

474
Index

– Parameter 149, 150


– Rückgabewert 149, 150
– Signatur 146
– Spezifizierer 159
– Stack 154
– static-Variablen 146
– statische Variablen 149
– Überladung 160
– Vorgabeargumente 153
Funktionentemplates 209
Funktionsadapter 463
Funktionsbereich 58
Funktionsobjekte 459
G
get_temporary_buffer() 466
Gleitkommazahlen 52
goto 142
greater 461
greater_equal 461
gslice 356, 448
gslice_array 450
Gültigkeitsbereiche 58
H
Header-Dateien 219
– der C++-Laufzeitbibliotheken 330
– der C-Laufzeitbibliotheken 247
– einbinden 30
I
if 132
indirect_array 451
Information hiding 167
Inkrement 103
inline 158, 159
Inline-Funktionen 147, 158
insert_iterator 387
Instanzbildung 188
int 51
invalid_argument 455
ios_base 402
isprint() 248
istream_iterator 388
istreambuf_iterator 389
iterator 391

475
Index

iterator_traits 390
Iteratoren 382
– Einfüge-Iteratoren 385
– Kategorien 382
– Stream-Iteratoren 387
K
Kapselung 167
Kernighan, Brian 14
Klassen 164
– Abgeschlossenheit 167
– abstrakte Klassen 201
– abstrakte Methoden 201
– Arrays von Objekten 188
– Basisklassenzeiger 202
– const-Datenelemente 170
– const-Methoden 175
– Datenelemente 168
– Deklaration in übergeordneter Klasse 172
– der C++-Laufzeitbibliotheken 357
– Destruktor 186
– eingebettete Objekte 170
– Einrichtung geerbter Elemente 183, 195
– Information hiding 167
– Instanzbildung 188
– Kapselung 167
– konstante Instanzen 188
– Konstruktor 183
– Konstruktorliste 171
– Kopierkonstruktor 184
– Methoden 173
– Objekte als Datenelemente 170
– objektorientierte Programmierung 166
– Standardkonstruktor 183
– Standardmethoden 187
– static-Datenelemente 169
– static-Methoden 174
– this-Zeiger 187
– verschachtelte Klassen 172
– Zugriff auf Basisklassenelemente 181
– Zugriff auf Elemente 178, 179
– Zugriffsspezifizierer 176
Klassenbereich 58

476
Index

Klassentemplates 210
– Methoden in Klassentemplates 211
Kommandozeilenargumente 148
Komma-Operator 127
Kommentare 25
Konsolenprogramme 19
Konstanten 94
– #define 96
– const-Variablen 98
– Literale 94
Konstruktoren 183
– bei Vererbung 194
– explicit-Deklaration 184
– Konstruktorliste 171, 195, 207
– Konvertierung in Klassentyp 184
– Kopierkonstruktor 184
– Mehrfachvererbung 196
– Standardkonstruktor 183
Konstruktorliste 171, 195, 207
Kopieren
– Klasseninstanzen 184
– Strings 73
Kopierkonstruktor 184
L
Laufzeitbibliotheken
– Algorithmen 392
– C 247
– C++ 329
– C++-Headerdateien 330
– C++-Klassen 357
– C-Funktionen 264
– C-Headerdateien 247
– Container 357
– Diagnoseklassen 453
– Iteratoren 382
– Lokale Klassen 425
– Numerische Klassen 443
– Stream-Klassen 400
– String-Klassen 420
– Typidentifizierung 458
– Utility-Klassen 459
Laufzeittypidentifizierung 203
– mit dynamic_cast 204

477
Index

– mit typeid 204


– mit virtuellen Methoden 203
Lebensdauer 64
left 339
Leistungsmerkmale 15
length_error 455
less 461
less_equal 461
Linker 34
list 365
Literale 94
locale 427
localeconv() 252
log() 253
log10() 253
logic_error 455
logical_and 461
logical_not 461
logical_or 461
Lokale 425
long 51
longjmp() 142, 253
M
main() 19, 147
– Argumente 148
Makros
– definieren 220
– versus Templates 208
Manipulatoren 244
map 367
mask_array 450
Mehrdateienprogramme 26
Mehrfachvererbung 204
– Konstruktoren 196
– Kreisschlüsse 206
– Namenskonflikte 205
– virtuelle Basisklassen 205
mem_fun() 464
mem_fun_ref() 464
mem_fun_ref_t 463
mem_fun_t 463
mem_fun1() 464
mem_fun1_ref() 464

478
Index

mem_fun1_ref_t 464
mem_fun1_t 463
messages 433
messages_base 433
messages_byname 434
Methoden 173
– abstrakte Methoden 201
– in Klassentemplates 211
– konstante 175
– nicht vererbbare Methoden 197
– statische 174
– Überladung 163
– Überschreibung 199
– virtuelle Methoden 199
minus 460
Modularisierung 26
modulus 460
money_base 435
money_get 434
money_put 435
moneypunct 436
moneypunct_byname 437
Multibyte-Zeichen 238
multimap 367
multiplies 460
multiset 375
mutable 160, 175
N
Namensbereiche 59
– deklarieren 60
– Elemente aus Namensbereich verwenden 60, 61
– erweitern 61
Namensgebung 17
namespace 60
negate 460
Negatoren für Funktionsobjekte 461
new 117
not_equal_to 461
not1() 462
not2() 462
num_get 437
num_put 438
numeric_limits 452

479
Index

Numerische Klassen 443


numpunct 439
numpunct_byname 440
O
operator 130, 131
Operatoren 99
– Adresse 126
– arithmetische 102
– Assoziativität 128
– Bedingungsoperator 126
– Bit-Operatoren 113
– Cast-Operator 93, 120
– const_cast 121
– Datenzugriff 109
– Dekrement 103
– delete 117
– dynamic_cast 121
– Gültigkeitsbereich 112
– Inkrement 103
– Komma-Operator 127
– logische 106
– new 117
– Priorität 128
– reinterpret_cast 123
– sizeof 125
– static_cast 122
– Streamoperatoren 116
– Synonyme 128
– typeid 124
– Überladung 129
– vergleichende 106
– Vorzeichen 101
– Zuweisungen 104
ostream_iterator 388
ostreambuf_iterator 390
out_of_range 455
overflow_error 455
P
pair 459
Parameter 149, 150
– als Adresse übergeben 151
– als Wert übergeben 151
– const-Deklaration 152

480
Index

plus 460
pointer_to_binary_function 463
pointer_to_unary_function 463
Polymorphie 197
pow() 253
Präprozessor 217
– Arbeitsweise 217
– Bedingte Kompilierung 222
– Diagnosemeldungen 225
– Grundsymbolverbindung 224
– Makros 220
– Pragma-Direktiven 226
– Quellcode einfügen 219
– Zeichenkettenbildung 224
Pragma-Direktiven 226
Priorität 128
priority_queue 372
private 177, 193
Programme
– Aufbau 17
– aus mehreren Quelldateien 26
– erstellen 34
– Kommandozeilenargumente 148
– Konsolenprogramme 19
– modularisieren 26
– typische Komponenten 20
Programmerstellung 34
Programmfluß 33
Programmsteuerung 132
– Schleifen 137
– Verzweigungen 132
protected 177, 193
ptr_fun() 463
public 177, 193
Pufferung 246
putchar() 248
Q
queue 373
R
range_error 455
raw_storage_iterator 466
Referenzen 87
– const-Deklaration 89

481
Index

register 56
reinterpret_cast 123
return 139, 142, 150
return_temporary_buffer() 466
reverse_iterator 384
Ritchie, Dennis 14
RTTI 203
– mit dynamic_cast 204
– mit typeid 204
– mit virtuellen Methoden 203
Rückgabewert 149, 150
runtime_error 456
S
Schleifen 137
– Abbruchbefehle 142
– do-while 141
– Endlosschleifen 139
– for 138
– while 139
Schlüsselwörter 44
set 375
set_new_handler() 456
set_terminate() 234, 456
set_unexpected() 234, 456
setjmp() 253
setlocale() 252
setw() 338
short 51
Sichtbarkeit 63
signal() 254
Signatur 146
signed 50, 53
sin() 253
sizeof 125
slice 447
slice_array 449
Speicherbelegung
– Aufzählungstypen 67
– für Gleitkommatypen 52
– für Integer-Typen 51
Speicherverwaltung
– Zeiger 81

482
Index

Spezialisierung, von Templates 212


sscanf() 261
stack 378
Stack (für Funktionsaufrufe) 154
Standardkonstruktor 183
Standardkonvertierungen 90
static 56, 159
static (Datenelemente) 169
static (Methoden) 160, 174
static_cast 122
stderr 240
stdin 240
stdout 240
strcmp() 236
strcpy() 236
Stream-Klassen 400
Streams
– Fehlerbehandlung in C++ 245
– in C 240
– in C++ 242
– Operatoren 116
– Pufferung 246
– Stream-Klassen 400
string 237
String-Klassen 420
Strings 235
– als Arrays 72
– initialisieren 73
– kopieren 73
– Laufzeittypidentifizierung 458
– Multibyte-Zeichen 238
– String-Klassen 420
– vergleichen 74
– Wide Characters 238
– Zugriff auf einzelne Zeichen 74
strlen() 248, 260
Stroustrup, Bjarne 14
struct 74
Strukturen 74
– Bitfelder 77
– in C++ 75
– Initialisierung 76

483
Index

– mit Elementen < 1 Byte 77


– Zugriff auf Elemente 76
switch 135
T
template 207
Templates 207
– explizite Instanziierung 215
– explizite Spezialisierung 216
– Friend-Deklarationen 210
– für Funktionen 209
– für Klassen 210
– implizite Instanziierung 213
– partielle Spezialisierung 216
– Spezialisierung 212
– versus Makros 208
terminate() 234, 457
this 187
this-Zeiger 87, 187
throw 142, 147, 230
time() 261
time_base 440
time_get 440
time_get_byname 441
time_put 442
time_put_byname 442
time_t 261
tolower() 248
Trigraphsequenzen 43
true 50
try 233
Typdefinitionen mit typedef 89
type_info 458
typedef 89
typeid 124, 204
typename 208
Typidentifizierung 119
– typeid 124
Typumwandlung 92, 119
– Cast-Operator 120
– const_cast 121
– dynamic_cast 121
– reinterpret_cast 123

484
Index

– static_cast 122
Typunabhängigkeit 207
U
Überladung
– von Funktionen 160
– von Methoden 163
– von Operatoren 129
Überschreibung 199
unary_function 460
unary_negate 461
uncaught_exception() 457
underflow_error 456
unexpected() 234, 457
UNICODE 235
uninitialized_copy() 466
uninitialized_fill() 466
uninitialized_fill_n() 466
union 79
Unions 79
unsigned 51, 53
using 60
Utility-Klassen 459
V
valarray 355, 444
Variablen 22, 48, 54
– globale 63
– Initialisierung 55
– Lebensdauer 64
– Sichtbarkeit 63
– Spezifizierer 55
– Verdeckung 63
vector 379
Verdeckung 63
Vererbung 189
– Bindung, späte 199
– Destruktoren 201
– Konstruktoren 194
– Mehrfachvererbung 204
– nicht vererbbare Methoden 197
– Polymorphie 197
– Überschreibung 199
– versus Einbettung 191
– Zugriffsrechte auflockern 194

485
Index

– Zugriffsspezifizierer 192
Vergleichen
– Operatoren 106
– Strings 74
Verzweigungen
– if 132
– if-else 133
– switch 135
virtual (Basisklassen) 190, 205
virtual (Methoden) 160, 199, 201
void 84, 146
volatile 55, 160
Vorzeichen 101
W
wchar_t 51, 238
Wertebereiche
– von Gleitkommazahlen 50
– von Integer-Datentypen 50
while 139
Wide Characters 238
width() 339
WinMain() 19
wstring 237
Z
Zeichenketten 235
– als Arrays 72
– initialisieren 73
– kopieren 73
– Multibyte-Zeichen 238
– String-Klassen 420
– vergleichen 74
– Wide Characters 238
– Zugriff auf einzelne Zeichen 74
Zeichensatz 41
Zeiger 81
– auf Datenelemente 85
– auf Funktionen 85
– auf Methoden 86
– auf statische Klassenelemente 86
– auf void 84
– auf Zeichenketten 84
– Basisklassenzeiger 86, 202
– Dereferenzierung 83

486
Index

– Einsatzgebiete 81
– Initialisierung 82
– konstante Zeiger 85
– NULL-Zeiger 82
– this 87
Zugriffsspezifizierer
– bei Vererbung 192
– in Klassendeklaration 176
Zuweisungen 104

487

Das könnte Ihnen auch gefallen