C – kurz & gut - Ulla Kirch - E-Book

C – kurz & gut E-Book

Ulla Kirch

0,0

Beschreibung

C – kurz & gut ist die praktische Taschenreferenz für jeden C-Programmierer. Das Buch ist ein nützlicher Begleiter, um schnell Informationen über ein bestimmtes Syntaxelement oder eine Bibliothek zu finden – unabhängig davon, ob Sie bereits Erfahrung mit C haben oder noch nicht mit der Sprache vertraut sind. Einsteiger in C können sich einen ersten Überblick über die Sprachfeatures verschaffen, für fortgeschrittene Programmierer ist das Buch die ideale Schnellreferenz. Das Buch besteht aus zwei Teilen: einer kompakten Beschreibung der Sprache und einer thematisch strukturierten Referenz der Standardbibliothek. Es wurde für die 2. Auflage vollständig aktualisiert, erweitert und durch Neuerungen wie beispielsweise die Multithreading-Bibliothek ergänzt. Die Darstellung im Buch basiert auf dem ISO-Standard C18. Aus dem Inhalt: - Grundlagen - Datentypen - Ausdrücke und Operatoren - Anweisungen - Deklarationen - Funktionen - Präprozessordirektiven - Die Standardbibliothek

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern
Kindle™-E-Readern
(für ausgewählte Pakete)

Seitenzahl: 190

Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:

Android
iOS
Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



C

kurz & gut

Ulla Kirch und Peter Prinz

Ulla Kirch und Peter Prinz

Lektorat: Alexandra Follenius

Korrektorat: Sibylle Feldmann, www.richtiger-text.de

Satz: III-satz, www.drei-satz.de

Herstellung: Stefanie Weidner

Umschlaggestaltung: Michael Oréal, www.oreal.de

Bibliografische Information der Deutschen Nationalbibliothek

Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.

ISBN:

Print      978-3-96009-107-3

PDF       978-3-96010-297-7

ePub      978-3-96010-298-4

mobi      978-3-96010-299-1

2. Auflage

Copyright © 2019 dpunkt.verlag GmbH

Wieblinger Weg 17

69123 Heidelberg

Dieses Buch erscheint in Kooperation mit O’Reilly Media, Inc. unter dem Imprint »O’REILLY«. O’REILLY ist ein Markenzeichen und eine eingetragene Marke von O’Reilly Media, Inc. und wird mit Einwilligung des Eigentümers verwendet.

Hinweis:

Dieses Buch wurde auf PEFC-zertifiziertem Papier aus nachhaltiger Waldwirtschaft gedruckt. Der Umwelt zuliebe verzichten wir zusätzlich auf die Einschweißfolie.

Schreiben Sie uns:

Falls Sie Anregungen, Wünsche und Kommentare haben, lassen Sie es uns wissen: [email protected].

Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen. Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen. Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.

5 4 3 2 1 0

Inhalt

Vorwort

C-Sprachbeschreibung

Grundlagen

Elementare Datentypen

Konstanten

Ausdrücke und Operatoren

Typumwandlungen

Anweisungen

Deklarationen

Variablen

Abgeleitete Typen

Funktionen

Bindung von Bezeichnern

Präprozessordirektiven

Standardbibliothek

Standard-Header-Dateien

Ein-/Ausgabe

Grenzwerte und Klassifizierung von Zahlen

Mathematische Funktionen

Zeichenklassifizierung/Umwandlung

String-Verarbeitung

Sortieren und Suchen

Speichermanipulationen

Dynamische Speicherverwaltung

Zeit und Datum

Prozesskontrolle

Multithreading

Internationalisierung

Funktionen mit Bereichsüberprüfung

Index

Zu diesem Buch – sowie zu vielen weiteren O’Reilly-Büchern – können Sie auch das entsprechende E-Book im PDF-Format herunterladen. Werden Sie dazu einfach Mitglied bei oreilly.plus+:

www.oreilly.plus

Vorwort

Die Programmiersprache C wurde in den 70er-Jahren von Dennis Ritchie in den Bell Labs (Murray Hill, USA) entwickelt, um das Betriebssystem UNIX auf einer DEC PDP-11 zu implementieren. Die Ursprünge der Sprache C gehen auf die typenlosen Programmiersprachen BCPL (Basic Combined Programming Language, entwickelt von M. Richards) und B (entwickelt von K. Thomson) zurück. 1978 wurde von Brian Kernighan und Dennis Ritchie die erste allgemein zugängliche Sprachbeschreibung veröffentlicht, der sogenannte K&R-Standard.

C ist eine in hohem Maße portable Sprache, die sich an der Architektur der heutigen Rechner orientiert. Der eigentliche Sprachkern ist relativ klein und enthält nur wenige hardwareabhängige Bestandteile. So gehören zum Sprachumfang weder Anweisungen für die Ein-/Ausgabe noch Speicherverwaltungstechniken. Für diese Aufgaben stehen Funktionen in der umfangreichen C-Standardbibliothek zur Verfügung.

In der Praxis ergeben sich daraus wesentliche Vorteile:

Portabilität auf Quellcodeebene.

Erzeugung von effizientem Maschinencode.

C-Compiler sind auf allen gängigen Systemen verfügbar.

Diese Referenz beschreibt im ersten Teil die Programmiersprache C und im zweiten Teil die C-Standardbibliothek. Die Sprachbeschreibung basiert auf der ISO/IEC-Norm 9899, die ursprünglich 1990 von der International Standards Organization verabschiedet, 1999 und 2011 wesentlich erweitert und zuletzt 2018 geringfügig geändert wurde.

Die ISO/IEC-Norm 9899 ist im Internet erhältlich unter

http://www.iso.org/standards.html

Der Standard von 1999 (ISO/IEC 9899:1999, kurz: C99) wird heute von allen gängigen C-Compilern unterstützt. Die Erweiterungen im Standard von 2011 (ISO/IEC 9899:2011, kurz: C11) und 2018 (ISO/ IEC 9899:2018, kurz: C18) sind noch nicht bei allen C-Compilern implementiert und werden deshalb im Buch mit C11 bzw. C18 gekennzeichnet. Zu den Erweiterungen von C11 gehören z. B. atomare und generische Typen sowie Multithreading. In C18 wurde lediglich das Makro __STDC_VERSION__ neu definiert, und die Fehlerbehandlung wurde verbessert.

C-Sprachbeschreibung

Grundlagen

Ein C-Programm besteht aus einzelnen »Bausteinen«, den Funktionen, die sich gegenseitig aufrufen.

Jede Funktion löst eine bestimmte Aufgabe. Sie ist entweder selbst erstellt oder eine fertige Routine aus der Standardbibliothek. Die Funktion main() hat eine besondere Rolle: Sie bildet das steuernde Hauptprogramm. Jede andere Funktion entspricht einem Unterprogramm.

Struktur eines C-Programms

Das obige Beispiel zeigt, wie ein C-Programm strukturiert ist. Das Programm besteht aus den Funktionen main() und showPage(). Es gibt den Anfang einer Textdatei aus, deren Name beim Starten des Programms in der Kommandozeile angegeben werden muss.

Die Anweisungen, aus denen die Funktionen bestehen, bilden zusammen mit den notwendigen Deklarationen und Präprozessordirektiven den Quellcode eines C-Programms. Dieser wird bei kleineren Programmen in eine Quelldatei geschrieben.

Größere C-Programme bestehen aus mehreren Quelldateien, die getrennt bearbeitet und übersetzt werden können. Dabei werden in einer Quelldatei die Funktionen zusammengefasst, die auch logisch eine Einheit bilden, wie etwa die Funktionen für die Bildschirmausgabe. Informationen, die in mehreren Quelldateien erforderlich sind, wie z. B. Deklarationen, werden in Header-Dateien gestellt. Diese können mit der #include-Direktive in eine Quelldatei kopiert werden.

Quelldateien haben die Endung .c, Header-Dateien die Endung .h. Eine Quelldatei zusammen mit den darin inkludierten Header-Dateien wird Übersetzungseinheit genannt.

Die Reihenfolge, in der Funktionen definiert werden, ist nicht vorgeschrieben. Zum Beispiel könnte die Funktion showPage() auch vor der Funktion main() stehen. Eine Funktion darf jedoch nicht innerhalb einer anderen Funktion definiert werden.

Zur Gestaltung der Quelldatei: Generell gilt, dass der Compiler jede Quelldatei sequenziell bearbeitet und den Inhalt in »Tokens« (kleinste Bestandteile) zerlegt, wie zum Beispiel Funktionsnamen und Operatoren. Tokens können durch beliebig viele Zwischenraumzeichen getrennt werden, also durch Leer-, Tabulator- oder Newline-Zeichen. Es kommt nur auf die Reihenfolge an und nicht auf ein bestimmtes Layout, wie etwa die Aufteilung in Zeilen und Spalten. Eine Ausnahme bilden die Präprozessordirektiven, also die Befehle, die der Präprozessor vor der Kompilierung ausführen soll. Sie beginnen mit dem Doppelkreuz # und nehmen stets eine eigene Zeile ein.

Kommentare sind Zeichenfolgen, die entweder durch /**/ eingeschlossen sind oder mit // beginnen und bis zum Zeilenende reichen. In der ersten Übersetzungsphase, in der noch kein Objektcode erzeugt wird, erfolgt die Ersetzung aller Kommentare durch ein Leerzeichen.

Außerdem werden die Präprozessordirektiven ausgeführt.

Zeichensätze

Der C-Standard unterscheidet zwei Zeichensätze: Der erste ist der Quellzeichensatz, der aus den Zeichen besteht, die in einer Quelldatei verwendet werden dürfen. Der zweite ist der Ausführungszeichensatz. Dieser besteht aus den Zeichen, die bei der Ausführung eines Programms interpretiert werden, wie z. B. die Zeichen eines Strings.

Beide Zeichensätze enthalten den Basiszeichensatz. Dieser umfasst

Der Ausführungszeichensatz enthält darüber hinaus noch folgende Zeichen:

das Null-Zeichen

\0

, um das Ende von Strings zu markieren

die Steuerzeichen, die durch einfache

Escape-Sequenzen

repräsentiert werden, um Ausgabegeräte wie Bildschirme oder Drucker zu steuern

Tabelle 1: Die standardisierten Escape-Sequenzen

Der numerische Wert eines Zeichens, der sogenannte Zeichencode, ist abhängig von der Implementierung. Im C-Standard ist lediglich festgelegt:

Jedes Zeichen des Basiszeichensatzes wird in einem Byte gespeichert.

Das Null-Zeichen wird in einem Byte dargestellt, in dem alle Bits den Wert

0

haben.

Der Zeichencode jeder Dezimalziffer ist um 1 größer als der Code ihres Vorgängers.

In Kommentaren, Strings und Zeichenkonstanten können – abhängig vom jeweiligen Compiler – beliebige andere Zeichen verwendet werden, zum Beispiel das Dollarzeichen oder deutsche Umlaute. Die Nutzung dieser Zeichen kann jedoch Auswirkungen auf die Portabilität haben. Alle verwendbaren Zeichen bilden den erweiterten Zeichensatz (engl. Extended Character Set), der stets den Basiszeichensatz umfasst.

Für die Darstellung von Zeichen des erweiterten Zeichensatzes, die zur Speicherung mehr als ein Byte erfordern, gibt es zwei Möglichkeiten:

Der Typ

wchar_t

(engl.

Wide Character Type

) ist geeignet, alle Zeichen des erweiterten Zeichensatzes in Codes fester Breite darzustellen.

wchar_t

ist ein ganzzahliger Typ, der in den Header-Dateien

stddef.h, stdlib.h

und

wchar.h

definiert ist. Viele Implementierungen verwenden die Unicode-Formate UTF-16 oder UTF-32, die den standardisierten ASCII-Code umfassen und Zeichen in zwei bzw. vier Bytes darstellen.

Multibyte-Zeichen werden in einem oder mehreren Bytes dargestellt. Dabei werden die Zeichen des Basiszeichensatzes in einem Byte gespeichert, und es ist sichergestellt, dass in keinem Multibyte-Zeichen außer dem Null-Zeichen alle Bits auf

0

gesetzt sind. Der UTF-8-Zeichensatz wurde entwickelt, um alle Unicode-Zeichen darzustellen. Er verwendet ein bis vier Bytes zur Darstellung eines Multibyte-Zeichens.

Zeichen, die nicht im Basiszeichensatz enthalten sind, können durch ihren universellen Zeichennamen (engl. Universal Character Name) dargestellt werden. Das ist der Unicode-Wert des Zeichens, der mit dem Präfix \u oder \U beginnt und vier bzw. acht Hexadezimalziffern besitzt.

Beispiel:

Universelle Zeichennamen können in Bezeichnern, Zeichenkonstanten und String-Literalen verwendet werden, um Zeichen darzustellen, die nicht im Basiszeichensatz enthalten sind. Sie werden jedoch nicht von allen Compilern unterstützt.

Der C-Standard unterstützt auch die Trigraph-Sequenzen. Diese erlauben es, wichtige grafische Zeichen auch auf Tastaturen einzugeben, die diese Zeichen nicht zur Verfügung stellen. Zum Beispiel kann das Zeichen | durch die Sequenz ??! dargestellt werden.

Tabelle 2: Die Trigraph-Sequenzen

Trigraph-Sequenz

Bedeutung

??=

#

??(

[

??/

\

??)

]

??'

^

??<

{

??!

|

??>

}

??-

~

Bezeichner

Bezeichner (engl. Identifier) sind Namen von Variablen, Funktionen, Makros, Datentypen usw. Für die Bildung von Bezeichnern gelten die folgenden Regeln:

Ein Bezeichner besteht aus einer Folge von Buchstaben (

A

bis

Z

,

a

bis

z

), Ziffern (

0

bis

9

), universellen Zeichennamen und Unterstrichen (

_

).

Die universellen Zeichennamen müssen Buchstaben und Ziffern einer Sprache repräsentieren.

Das erste Zeichen darf keine Ziffer sein, auch kein universeller Zeichenname, der eine Ziffer repräsentiert.

Groß- und Kleinbuchstaben werden unterschieden.

Ein Bezeichner kann beliebig lang sein. Signifikant sind in der Regel nur die ersten 31 Zeichen.

Schlüsselwörter sind reserviert und dürfen nicht als Bezeichner verwendet werden. Die Schlüsselwörter in alphabetischer Reihenfolge:

auto

break

case

char

const

continue

default

do

double

else

enum

extern

float

for

goto

if

inline

int

long

register

restrict

return

short

signed

sizeof

static

struct

switch

typedef

union

unsigned

void

volatile

while

_Alignas

_Alignof

_Atomic

_Bool

_Complex

_Generic

_Imaginary

_Noreturn

_Static_assert

_Thread_local

Daneben gibt es reservierte Bezeichner, wie z. B. Namen von Standardfunktionen oder Standardmakros, die in einem Programm nicht als Bezeichner für Variablen, Funktionen, Datentypen usw. verwendet werden dürfen. Auch Namen, die mit zwei Unterstrichen oder einem Unterstrich und einem Großbuchstaben beginnen, sind reservierte Bezeichner.

Für externe Namen (Bezeichner von Funktionen und Variablen mit externer Bindung) sind weitere Einschränkungen möglich, die vom jeweiligen Linker abhängen: In portablen C-Programmen sollten externe Namen so gewählt werden, dass nur die ersten acht Zeichen signifikant sind, auch wenn der Linker Groß- und Kleinbuchstaben nicht unterscheidet.

Beispiele für Bezeichner:

gültig: a, DM, dm, FLOAT, _var1, topOfWindow

ungültig: do, 586_cpu, zähler, nl-flag, US_$

Namensklassen und Geltungsbereiche

Jeder Bezeichner gehört zu genau einer der vier Namensklassen, nämlich:

Namen von

Marken

(engl.

Labels

).

Namen von Strukturen, Unions und Aufzählungen (

Tags

). Das sind Namen, die einem der Schlüsselwörter

struct, union

oder

enum

folgen (siehe den Abschnitt

Abgeleitete Typen

auf

Seite 53

).

Namen von

Struktur

- oder

Union-Komponenten

. Jeder Strukturoder Union-Typ hat eine separate Namensklasse für seine Komponenten.

Alle anderen Bezeichner. Diese heißen auch

gewöhnliche Bezeichner

.

Bezeichner verschiedener Namensklassen dürfen identisch sein. So kann z. B. ein Label-Name auch gleichzeitig als Funktionsname verwendet werden. Am häufigsten werden jedoch Namensklassen im Zusammenhang mit Strukturen eingesetzt: Der gleiche Bezeichner kann als Struktur-, Komponenten- und Variablenname benutzt werden.

Beispiel:

struct person { char *person; /*...*/} person;

Auch die Komponenten verschiedener Strukturen können gleiche Namen haben.

Jeder Bezeichner hat innerhalb der Quelldatei seinen Geltungsbereich. Das ist der Teil, in dem der Bezeichner verwendet werden kann. Die vier möglichen Geltungsbereiche sind:

Funktionsprototyp

Bezeichner, die in der Parameterliste eines Prototyps stehen, haben den Geltungsbereich Funktionsprototyp. Dieser endet mit dem Prototyp. Solche Bezeichner haben damit nur den Charakter eines Kommentars.

Funktion

Nur Namen von Marken (Labels) haben den Geltungsbereich Funktion. Der Geltungsbereich besteht aus dem Funktionsblock, in dem das Label definiert ist. Label-Namen müssen in einer Funktion eindeutig sein. Die goto-Anweisung führt einen Sprung zu einem Label in derselben Funktion aus.

Block

Bezeichner, die in einem Block deklariert und keine Marken sind, haben den Geltungsbereich Block. Auch die Parameter in einer Funktionsdefinition haben den Geltungsbereich Block. Er beginnt mit der Deklaration und endet mit der Klammer }, die den Block schließt.

Datei

Bezeichner, die außerhalb aller Blöcke deklariert sind und zu keinem Prototyp gehören, haben den Geltungsbereich Datei. Dieser beginnt mit der Deklaration des Bezeichners und reicht bis zum Ende der Quelldatei.

Ein Bezeichner, der kein Label-Name ist, muss nicht notwendigerweise in seinem ganzen Geltungsbereich sichtbar sein: Wird nämlich der Bezeichner mit derselben Namensklasse in einem inneren Block erneut deklariert, ist die äußere Deklaration vorübergehend verdeckt. Die äußere Deklaration wird wieder sichtbar, wenn der Geltungsbereich für die innere Deklaration endet.

Elementare Datentypen

Der Typ einer Variablen bestimmt, wie viel Speicher diese Variable belegt und wie das dort gespeicherte Bitmuster interpretiert wird. Entsprechend bestimmt der Typ einer Funktion, wie der Return-Wert interpretiert werden muss.

Datentypen sind entweder vordefiniert oder abgeleitet. Die vordefinierten Datentypen in C sind die elementaren Typen (engl. Basic Types) und der Typ void. Die elementaren Typen bestehen aus den ganzzahligen Typen (engl. Integer Types) und den Gleitpunkttypen (engl. Floating Types).

Ganzzahlige Typen

Es gibt fünf ganzzahlige Typen mit Vorzeichen, nämlich signed char, short int (kurz: short), int , long int (kurz: long) und long long int (kurz: long long). Jedem dieser Typen entspricht ein ganzzahliger Typ ohne Vorzeichen, der den gleichen Speicherplatz belegt. Den vorzeichenlosen Typ erhält man durch Voranstellen des Typspezifizierers unsigned, also z. B. unsigned int.

Die Typen char, signed char und unsigned char sind formal verschieden. Je nach Einstellung des Compilers ist aber char gleichbedeutend mit signed char oder mit unsigned char. Dagegen hat der Typspezifizierer signed für die Datentypen short, int, long und long long keine Bedeutung, da sie stets mit Vorzeichen interpretiert werden. So bezeichnen z. B. short und signed short denselben Datentyp.

Die Größe der ganzzahligen Typen ist nicht festgelegt. Es gilt aber folgende Reihenfolge: char <= short <= int <= long <= long long. Der Typ short ist hierbei mindestens 2 Byte, der Typ long mindestens 4 Byte und der Typ long long mindestens 8 Byte groß. Die aktuellen Wertebereiche können der Header-Datei limits.h entnommen werden.

Außerdem gibt es den Typ _Bool, der mit C99 zur Darstellung boolescher Werte eingeführt wurde. Der boolesche Wert true (»wahr«) wird durch 1 und false (»falsch«) durch 0 repräsentiert. Sofern die Header-Datei stdbool.h inkludiert ist, können auch bool statt _Bool und die Bezeichner true und false verwendet werden.

Tabelle 3: Die ganzzahligen Typen mit Speicherplatz und Wertebereich

Typ

Speicherplatz

Wertebereich (dezimal)

_Bool

1 Byte

0 und 1

char

1 Byte

–128 bis 127 bzw. 0 bis 255

unsigned char

1 Byte

0 bis 255

signed char

1 Byte

–128bis 127

int

2 Byte oder 4 Byte

–32.768 bis 32.767 oder –2.147.483.648 bis 2.147.483.647

unsigned int

2 Byte oder 4 Byte

0 bis 65.535 oder 0 bis 4.294.967.295

short

2 Byte

–32.768 bis 32.767

unsigned short

2 Byte

0 bis 65.535

long

4 Byte

–2.147.483.648 bis 2.147.483.647

unsigned long

4 Byte

0 bis 4.294.967.295

long long

8 Byte

–9.223.372.036.854.775.808 bis 9.223.372.036.854.775.807

unsigned long long

8 Byte

0 bis 18.446.744.073.709.551.615

Tabelle 4: Ganzzahlige Typen vorgegebener Breite

Typ

Bedeutung

intN_t

Breite exakt N Bits.

int_leastN_t

Breite mindestens N Bits.

int_fastN_t

Schnellster Typ mit Mindestbreite von N Bits.

intmax_t

Breite maximal (größter ganzzahliger Typ).

intptr_t

Breit genug, um den Wert eines Zeigers zu speichern.

Beispiel:

Zu jedem der oben angegebenen signed-Typen gibt es auch einen unsigned-Typ mit dem Präfix u. So ist uintmax_t der unsigned-int-Typ maximaler Breite.

Seit C11 sind in der Header-Datei uchar.h die Typen char16_t und char32_t für Unicode-Zeichen definiert, die in 16 Bit oder in 32 Bit dargestellt werden können. Die Typen entsprechen den Typen uint_least16_t bzw. uint_least32_t. Zeichen des Typs char16_t sind in Implementierungen, die das Makro __STDC_UTF_16__ definieren, im UTF-16-Format codiert. Ist das Makro __STDC_UTF_32__ definiert, sind Zeichen des Typs char32_t im UTF-32-Format codiert.

Reelle und komplexe Gleitpunkttypen

Zur Darstellung von Zahlen mit gebrochenem Anteil (= reelle Zahlen) gibt es die drei Typen float, double und long double. Diese drei Datentypen werden reelle Gleitpunkttypen genannt.

Tabelle 5: Reelle Gleitpunktzahlen

In der Header-Datei float.h sind symbolische Konstanten definiert, die alle Aspekte der verwendeten Darstellung beschreiben (siehe Teil 2, Grenzwerte und Klassifizierung von Zahlen).

Interne Darstellung einer reellen Gleitpunktzahl

Die Darstellung einer Gleitpunktzahl x beruht immer auf einer Zerlegung in ein Vorzeichenv, eine Mantissem und einen Exponentenexp zur Basis 2:

Die Genauigkeit eines Typs wird durch die Anzahl der Bits bestimmt, die die Mantisse im Speicher belegt. Dagegen wird der Wertebereich durch die Anzahl der Bits für den Exponenten bestimmt.

Die Speicherbelegung im IEEE-Format für den Typ float (32 Bit):

Das Vorzeichenbit Vz hat für negative Zahlen den Wert 1, sonst den Wert 0. Die erste binäre Ziffer der Mantisse ist stets 1. Sie wird daher nicht gespeichert. Der Exponent wird mit einer Verschiebung (Bias) gespeichert: Bei float beträgt das Bias 127.

Beispiel:

Komplexe Gleitpunkttypen

Mit C99 wurden auch Gleitpunkttypen zur Darstellung der komplexen Zahlen und insbesondere der rein imaginären Zahlen eingeführt. Jede komplexe Zahl z ist in kartesischen Koordinaten wie folgt darstellbar:

Daneben gibt es auch die Darstellung in Polarkoordinaten:

Der Winkel theta heißt Argument und die Zahl rAbsolutbetrag von z.

In C wird eine komplexe Zahl mit dem Real- und Imaginärteil als float-, double- oder long double-Wert dargestellt. Entsprechend gibt es die komplexen Gleitpunkttypen

float _Complex, double _Complex , long double _Complex.

float _Imaginary, double _Imaginary, long double _Imaginary

Die komplexen Gleitpunkttypen sind in der Header-Datei complex.h definiert. Falls das Makro __STDC_IEC_559_Complex__ definiert ist, unterstützt die Implementierung die komplexe Gleitpunktarithmetik entsprechend der Norm IEC 60559.

Die reellen und komplexen Gleitpunkttypen bilden zusammen die Gleitpunkttypen.

Der Typ void

Der Typspezifizierer void zeigt an, dass kein Wert vorhanden ist. Er wird in drei verschiedenen Situationen verwendet:

1. Ausdrücke vom Typ void

Für void-Ausdrücke gibt es zwei Anwendungen. Zum einen werden Funktionen, die keinen Return-Wert liefern, als void deklariert.

Beispiel:

void exit(int status);

Zum anderen kann mit der Cast-Konstruktion (void)Ausdruck der Wert eines Ausdrucks explizit verworfen werden.

Beispiel:

(void)printf("Ein Beispiel");

2. Prototyp von Funktionen mit leerer Parameterliste

Beispiel:

int rand(void);

3. void-Zeiger

Zeiger vom Typ void * repräsentieren die Adresse eines Objekts, aber keinen Typ. Solche »typenlosen« Zeiger werden vor allem bei Funktionen verwendet, die mit unterschiedlichen Zeigertypen aufgerufen werden können.

Beispiel:

void *memcpy(void *ziel, void *quelle,

size_t anzahl);

Ausrichtung von Objekten im Speicher

Objekte eines bestimmten Typs können nur an Adressen gespeichert werden, die ein bestimmtes Vielfaches einer Byte-Adresse sind. Diese Anforderung an den Typ wird Ausrichtung (engl. Alignment) genannt. Die Ausrichtung ist durch eine Ganzzahl festgelegt, die den Mindestabstand in Byte zwischen zwei Objekten desselben Typs angibt. Diese Zahl (kurz: Alignment) ist eine nicht negative Potenz von 2, jedoch abhängig von der Implementierung. Ihr Wert hat den Typ size_t und kann seit C11 mit dem Operator _Alignof bestimmt werden.

Beispiel:

_Alignof(int) // Liefert typischerweise den Wert 4

Ist der Operand von _Alignof ein Vektor fester Länge, liefert der Operator die Ausrichtung der Vektorelemente.

Die möglichen Werte für das Alignment sind ihrer Größe nach geordnet. Ein größerer Wert bedeutet ein strikteres Alignment. So ist das Alignment des Typs long long im Allgemeinen strikter als das Alignment für den Typ float.

In der Deklaration eines Objekts kann ein strikteres Alignment festgelegt werden, als durch den Typ des Objekts vorgegeben ist. Hierfür steht der Spezifizierer _Alignas zur Verfügung. Er erwartet als Argument einen Typnamen oder einen konstanten ganzzahligen Ausdruck, der einen zulässigen Wert für das von der Implementierung unterstützte Alignment darstellt.

Beispiel:

_Alignas(double) float x; // Deklariert x mit dem

// Typ float und dem

// Alignment von double

Der Spezifizierer darf weder in Verbindung mit typedef und register noch in der Deklaration einer Funktion oder eines Bitfelds angegeben werden.

Nach dem Inkludieren der Header-Datei stdalign.h können die Makros alignof und alignas anstelle von _Alignof und _Alignas eingesetzt werden.

Konstanten

Jede Konstante ist entweder eine ganzzahlige Konstante, eine Gleitpunktkonstante, eine Zeichenkonstante oder ein String-Literal. Außerdem gibt es Aufzählungskonstanten, die unter Aufzählungstypen beschrieben sind. Jede Konstante hat einen Typ, der sich aus ihrem Wert und der Schreibweise ergibt.

Ganzzahlige Konstanten

Ganzzahlige Konstanten können als gewöhnliche Dezimalzahlen, Oktalzahlen oder Hexadezimalzahlen dargestellt werden:

Eine

dezimale Konstante

(Basis 10) beginnt mit einer von

0

verschiedenen Ziffer. Beispiel:

1024

.

Eine

oktale Konstante

(Basis 8) beginnt mit einer führenden

0

. Beispiel:

012

.

Eine

hexadezimale Konstante

(Basis 16) beginnt mit den beiden Zeichen

0x

oder

0X

. Beispiele:

0x7f

oder

0X7f

oder

0x7F

oder

0X7F

. Die Ziffern

A

bis

F

können groß- oder kleingeschrieben werden.

Der Typ einer ganzzahligen Konstanten ist der erste in der folgenden Abstufung, der ihren Wert darstellen kann.

Für dezimale Konstanten gilt diese Abstufung:

int, long, long long

Für oktale oder hexadezimale Konstanten gilt diese Abstufung:

int, unsigned int, long, unsigned long,

long long, unsigned long long

Ganzzahlige Konstanten haben also in der Regel den Typ int. Der Typ kann auch direkt durch die Suffixe L oder l (für long), LL oder ll (für long long) bzw. U oder u (für unsigned) beeinflusst werden.

Tabelle 6: Beispiele für ganzzahlige Konstanten