22.9 Erweiterter ANSI C-Standard (ANSI C99)
 
Ursprünglich war für den erweiterten ANSI-C-Standard ein extra Kapitel vorgesehen. Aber um den Umfang des Buchs nicht zu sprengen und Ihre Geduld nicht allzu sehr zu strapazieren, werden diese Erweiterungen hier in einer kurzen Zusammenfassung erwähnt. Sie stellt keine Referenz der Erweiterungen dar, sondern fasst lediglich das Wichtigste in Kürze zusammen. Für eine detailliertere Auflistung (u.a.) aller C99-Funktionen sei bei Bedarf die Webseite http://www.dinkumware.com/refxc.html empfohlen.
Hinweis Es kann sein, dass dieser erweiterte ANSI C99-Standard bei vielen Compilern noch gar nicht implementiert ist und deshalb auch nicht funktioniert.
|
22.9.1 Neue elementare Datentypen
 
Zur Darstellung der boolschen Werte 1 und 0 wurde der Typ _Bool eingeführt. Der Wertebereich von _Bool beträgt 0 und 1. Wenn Sie die Headerdatei <stdbool.h> inkludieren, können Sie auch bool statt _Bool schreiben und die Bezeichner true für 1 und false für 0 verwenden.
Weitere zwei Ganzzahltypen, die eingeführt wurden, sind long long und unsigned long long, welche beide 8 Bytes Speicherplatz belegen. Hier ein Überblick der neuen Ganzzahltypen des C99-Standards:
Tabelle 22.6
Neue ganzzahlige Typen
Typ
|
Speicherplatz
|
Wertebereich
|
_Bool
|
1 Byte
|
0 und 1
|
long long
|
8 Byte
|
–9223372036854775808
bis 9223372036854775807
|
unsigned long long
|
8 Byte
|
0 bis 18446744073709551615
|
22.9.2 <stdint.h> – Ganzzahlige Typen mit vorgegebener Breite
 
In der Headerdatei <stdint.h> befinden sich weitere Ganzzahldatentypen, die mit vorgegebener Breite verwendet werden. Mit vorgegebener Breite ist die Anzahl der Bits zur Darstellung des Werts gemeint, welche dieser Typ verwenden darf. Hier die Typen im Überblick:
Tabelle 22.7
Neue ganzzahlige Typen vorgegebener Breite
Typ
|
Bedeutung
|
intN_t
|
Ein int-Wert mit einer Breite von exakt N Bits
(erlaubte Werte für N: 8, 16, 32, 64)
|
int_leastN_t
|
Ein int-Wert mit einer Breite von mindestens N Bits
(erlaubte Werte für N: 8, 16, 32, 64)
|
int_fastN_t
|
Der schnellste int-Typ mit mind. einer Breite von N Bits
(erlaubte Werte für N: 8, 16, 32, 64)
|
intmax_t
|
Größtmöglicher ganzzahliger Typ (Wert ist in der Konstante INT64_MAX bzw. UINT64_MAX deklariert)
|
intptr_t
|
Max. Breite, um den Wert eines Zeigers zu speichern
|
Zu allen diesen Ganzzahltypen gibt es jeweils einen unsigned-Bruder, der nur ein u vorangestellt hat (z.B. uintptr_t). Die maximalen und minimalen Limits dieser Ganzzahltypen sind ebenfalls in der Headerdatei <stdint.h> deklariert.
22.9.3 Komplexe Gleitpunkttypen
 
Zur Darstellung von komplexen und imaginären Zahlen wurden mit ANSI C99 weitere Gleitpunkttypen eingeführt. Die komplexe Zahl wird dabei mit dem Real- und Imaginärteil dargestellt, und zwar als float, double oder long double-Wert. Die Schreibweise dieser Gleitpunkttypen sieht wie folgt aus:
|
komplexe Gleitpunkttypen: float _Complex, double _Complex und long double _Complex |
|
imaginäre Zahl: float _Imaginary, double _Imaginary und long double _Imaginary |
22.9.4 <iso646.h> – Symbolische Konstanten für Operatoren
 
In der Headerdatei <iso646.h> befinden sich einige symbolische Konstanten, welche Sie als Alternativen zu einigen Operatoren nutzen können. Hierzu eine Tabelle mit der jeweiligen symbolischen Konstante:
Tabelle 22.8
Alternative symbolische Konstanten für Operatoren
Konstante in <iso646.h>
|
Operator
|
and
|
&& (logisches UND)
|
or
|
|| (logisches ODER)
|
not
|
! (logisches NICHT)
|
bitand
|
& (bitweises UND)
|
bitor
|
| (bitweises ODER)
|
xor
|
^ (bitweises Exklusiv-ODER)
|
compl
|
~ (bitweises NICHT)
|
and_eq
|
&= (bitweises UND mit Zuweisung)
|
or_eq
|
|= (bitweises ODER mit Zuweisung)
|
xor_eq
|
^= (bitweises Exklusiv-ODER mit Zuweisung)
|
not_eq
|
!= (logisches NICHT mit Zuweisung)
|
22.9.5 Deklaration von Bezeichnern
 
Neu beim ANSI C99-Standard ist, dass die Deklaration im Anweisungsblock frei platziert werden kann und nicht mehr am Anfang des Blocks erfolgen muss.
22.9.6 inline-Funktionen
 
inline-Funktionen sind dem C++-Programmierer ja bereits wohlbekannt und stehen mit dem C99-Standard auch dem C-Programmierer zur Verfügung. Um eine Funktion als inline-Funktion anzugeben, muss dieser nur das Schlüsselwort inline vorangestellt werden:
/* inliner.c */
#include <stdio.h>
#include <stdlib.h>
inline void xchange(int *z1, int *z2) {
int tmp;
tmp = *z2;
*z2 = *z1;
*z1 = tmp;
}
inline void print(int *z1, int *z2) {
printf("%d :: %d\n", *z1, *z2);
}
int main(void) {
int zahl1 = 123, zahl2 = 321;
print(&zahl1, &zahl2);
xchange(&zahl1, &zahl2);
print(&zahl1, &zahl2);
return EXIT_SUCCESS;
}
inline-Funktionen stellen eine sinnvolle Alternative zu parametrisierten define-Makros dar. Der Code der inline-Funktion wird vom Compiler direkt an der Stelle eingefügt, an der der Aufruf stattfindet. Damit entfällt der Sprung in ein Unterprogramm, das heißt, der Aufwand mit dem Stack entfällt.
Die inline-Funktionen sollten aber möglichst klein gehalten werden. Werden zu viele Anweisungen verwendet, kann der Compiler das Schlüsselwort inline auch ignorieren und es als eine normale Funktion behandeln.
22.9.7 Vordefinierte Makros
 
Außer den bisher bekannten vordefinierten Makros, wie __LINE__, __FILE__, __DATE__, __TIME__ und __STDC__, sind weitere drei Makros hinzugekommen.
Tabelle 22.9
Neue vordefinierte Standardmakros
Makro
|
Bedeutung
|
__func__
|
Gibt den Namen der Funktion aus, in der dieses Makro verwendet wird.
|
__STD_HOSTED__
|
Wenn es sich um eine Hosted-Implementierung der Standardbibliothek handelt, ist diese Konstante 1, ansonsten 0.
|
__STD_VERSION__
|
Wenn der ANSI C99 Standard unterstützt wird, ist diese Konstante 199901L (1999 Januar).
|
Ein Beispiel mit dem Makro __func__, welches sich prima zum Debuggen von Programmen eignet.
/* stdmakro.c */
#include <stdio.h>
#include <stdlib.h>
void eine_funktion(void) {
printf("Name der Funktion: %s\n",__func__);
}
int main(void) {
eine_funktion();
return EXIT_SUCCESS;
}
22.9.8 <math.h> – Neue Funktionen
 
Enorm erweitert wurde die Headerdatei <math.h>. Darin befinden sich jetzt noch mehr Funktionen und Makros als zuvor. Zu allen Funktionen, die Sie bereits kennen und denen, welche Sie in diesem Abschnitt noch kennen lernen, wurden Versionen herausgebracht, die jetzt auch für die Datentypen float und long double anwendbar sind. Bisher waren die Funktionen dieser Headerdatei ja nur mit double angegeben. Um die für den Datentyp passende Funktion zu verwenden, müssen Sie nur ein entsprechendes Suffix notieren. f steht für float, l für long double und keine Angabe steht – wie gehabt – für double-Gleitpunktzahlen. Als Beispiel die Funktion sqrt():
float sqrtf(float zahl);
double sqrt(double zahl);
long double sqrtl(long double zahl);
In der folgenden Tabelle finden Sie einige Funktionen, die neu in die Headerdatei <math.h> hinzugekommen sind. Zu all diesen Funktionen gibt es auch schon verschiedene Versionen. Es hängt davon ab, welches Suffix Sie verwenden.
Tabelle 22.10
Neue mathematische Funktionen
Funktionen
|
Bedeutung
|
double round (double);
double trunc (double);
double rint (double x)
|
Funktionen zum Runden von Zahlen
|
double fmax (double, double);
double fmin (double, double);
|
Maximum, Minimum
|
double log2 (double _x);
double logb (double);
|
Logarithmus
|
double copysign (double, double);
|
Vorzeichen kopieren
|
double scalb (double, long);
extern double fma (double,
double, double);
|
Laufzeitoptimierte Berechnungen
|
double hypot (double, double);
|
Wurzel
|
Sehr interessant dürften die Makros für den Vergleich von Gleitpunktzahlen sein, welche ebenfalls hinzugekommen sind:
Tabelle 22.11
Makros zum Vergleichen von Gleitpunktzahlen
Makro
|
Bedeutung
|
isgreater(x, y)
|
x größer als y
|
isgreaterequal(x, y)
|
x größer als oder gleich y
|
isless(x, y)
|
x kleiner als y
|
islessequal(x, y)
|
x kleiner als oder gleich y
|
islessgreater(x, y)
|
x kleiner als y ODER x größer als y
|
isunordered(x, y)
|
Sind x und y nicht miteinander vergleichbar, gibt dieses Makro 1 zurück, ansonsten 0
|
Ein weiteres interessantes Feature sind Makros zur Bestimmung der Kategorie von Gleitpunktzahlen. In ANSI C werden die Gleitpunktzahlen in folgende fünf Kategorieren unterteilt (Konstanten aus der Headerdatei <math.h>):
Tabelle 22.12
Bestimmung der Gleitpunktzahl-Kategorie
Konstante
|
Kategorie
|
FP_NAN
|
NAN steht für Not a Number und bedeutet, dass es sich bei dem Wert um keine gültige Gleitpunktdarstellung handelt.
|
FP_NORMAL
|
Eine Gleitpunktzahl in normaler Darstellung
|
FP_INFINITE
|
Die Gleitpunktzahl wird als unendlicher Wert dargestellt.
|
FP_ZERO
|
Eine Gleitpunktzahl mit dem Wert 0
|
FP_SUBNORMAL
|
Eine Gleitpunktzahl, mit der besonders kleine Zahlen dargestellt werden können
|
Abfragen, in welche Kategorie eine bestimmte Gleitpunktzahl fällt, können Sie mit den folgenden Makros vornehmen:
Tabelle 22.13
Makros zur Bestimmung der Gleitpunktzahl-Kategorie
Makro
|
Bedeutung
|
isnan(x)
|
Ist die Zahl gleich FP_NAN, wird 1 zurückgegeben, ansonsten 0.
|
isnormal(x)
|
Ist die Zahl gleich FP_NORMAL, wird 1 zurückgegeben, ansonsten 0.
|
isfinite(x)
|
Ist die Zahl eine Unendliche, wird 1 zurückgegeben, ansonsten 0.
|
isinf(x)
|
Ist die Zahl gleich FP_INFINITE, wird 1 zurückgegeben, ansonsten 0.
|
Intern werden alle diese Makros jedoch zum Teil mit Hilfe des Makros fpclassify() ausgewertet:
fpclassify(x) == FP_INFINITE //isinf(x)
fpclassify(x) == FP_NORMAL //isnormal(x)
22.9.9 <wchar.h> – (NA1)
 
Die Headerdatei <wchar.h> wurde ebenfalls mit Normative Amendment 1 1995 hinzugefügt. In dieser Headerdatei sind folgende Funktionen enthalten:
|
Umwandlung von Strings zu Zahlwerten für den erweiterten Zeichensatz. |
|
String- und Speicherbearbeitung für den erweiterten Zeichensatz. |
|
Ein- und Ausgabe für den erweiterten Zeichensatz. |
Eine genauere Erläuterung der einzelnen Funktionen würde an dieser Stelle zu weit gehen. Aber im Allgemeinen sind Ihnen diese Funktionen schon u.a. aus der <stdio.h>- und <string.h>-Headerdatei bekannt. Hier handelt es sich bei dem ..w.. im Funktionsnamen um dieselben Funktionen wie Sie diese bereits aus den eben aufgeführten Headerdateien kennen, nur, dass sich diese auf den erweiterten Zeichensatz beziehen. Also: fgetwc() ist die Alternative für den erweiterten Zeichensatz der Funktion fgetc() zum Einlesen einzelner Zeichen aus einem FILE-Stream.
22.9.10 <wctype.h> (NA1)
 
Die Headerdatei <wctype.h> wurde ebenfalls wie <iso646.h> und <wchar.h> mit Normative Amendment 1 hinzugefügt. Diese Headerdatei enthält Zeichenklassifizierungen und Umwandlungen für den erweiterten Zeichensatz (einfach, ctype.h für den erweiterten Zeichensatz ist wctype.h). Auch hier gilt dasselbe wie schon bei der Headerdatei <wchar.h>. Die Bedeutung der einzelnen Funktionen entspricht exakt der, die Sie aus der Headerdatei <ctype.h> bereits kennen – nur, dass sich diese Funktionen auf den erweiterten Zeichensatz beziehen und wieder den Buchstaben ..w.. (für wide-char) im Funktionsnamen enthalten. Also, anstatt isalpha() lautet das Gegenstück für den erweiterten Zeichensatz iswalpha().
Jede Funktion erwartet als Argument einen Typ win_t, was ein Wert zwischen 0 und 32767 (oder WEOF) ist.
22.9.11 <fenv.h> – Kontrolle der Gleitpunkzahlen-Umgebung
 
In der Headerdatei <fenv.h> (für Floating Environment = Gleitpunkt-Umgebung) wurden zwei neue Typen, mehrere Makros und einige Funktionen zum Testen auf Fehlersituationen beim Rechnen mit Gleitpunktzahlen implementiert. Diese Umgebung enthält die Systemvariable fexept_t, welche von Gleitpunkt-Exceptions-Funktionen gesetzt werden kann, und die Variable fenv_t, welche für den Kontroll-Modus (bspw. des Rundungsverhaltens) verwendet wird.
22.9.12 <inttypes.h> – Für genauere Integer-Typen
 
Diese Headerdatei beinhaltet weitere Typen, mehrere Funktionen und Makros, welche recht nützlich zur Verwendung von und mit Integer-Typen sind. Das ANSI C-Komitee hat diese Headerdatei eingeführt, um endlich Integer-Typen zu unterstützen, die unabhängig von der Maschine und dem Betriebssystem sein sollen. Bspw. beträgt auf einem 16 Bit-System die Bitanzahl für char, short, int und long 8, 16, 16 und 32 Bits. Auf einem 32 Bit-System hingegeben 8, 16, 32 und 32 Bits. Hierbei wurden mit typdef Integer-Typen verschiedenster Größe erstellt. Diese neue Definierung von Integer-Typen ist (wird) auf jeden Fall sinnvoll, gerade, da jetzt auch noch die Einführung der 64 Bit-Systeme auf dem Massenmarkt aktuell ist.
22.9.13 <tgmath.h> – Typengenerische Mathematik-Funktionen
 
In der Headerdatei <tgmath.h> befinden sich typengenerische Mathematik-Funktionen (bzw. Makros). Darunter versteht man, dass Sie verschiedene mathematische Funktionen mit verschiedenen Argumenten wie reelle und/oder komplexe Gleitpunkttypen mit demselben Namen aufrufen können – es wird also immer die Funktion aufgerufen, welche dem Datentyp des Argumentes entspricht. Bspw.:
float _Complex fx;
long double lx;
// gleich zu cos((double)1)
cos(1) ;
// gleich zu cosl(lx)
cos(lx) ;
/* gleich zu:
* cpowl((long double _Complex)fx, (long double _Complex)lx) */
pow(fx, lx) ;
Ist eine Funktion hingegen nur für reelle und/oder komplexe Gleitpunkttypen definiert, dann entspricht der Name des typengenerierten Makros dem der Funktion, welche ursprünglich für double definiert ist.
22.9.14 Zusammenfassung
 
Dies soll es nun gewesen sein bezüglich der Erweiterungen des neuen ANSI C99-Standards. Es gibt noch einige mehr, die in diesem Abschnitt aber nicht angesprochen wurden.
Einige Leser werden sich wohl fragen: Wo bleibt denn der neue ANSI C99-Standard? Immerhin sind jetzt schon einige Jahre vergangen (und die zweite Auflage des Buches ist auch schon da ;-)), und es gibt immer noch keinen Compiler, der dem ANSI C99-Standard vollständig entspricht. Der gcc-Compiler wird diesen Standard wohl in ferner Zukunft erfüllen, aber bei den Compilern für Microsoft-Systeme sind in dieser Hinsicht keine Ansätze zu sehen. Es hat also den Anschein, dass sich der C99-Standard nicht mehr – wie noch der C89-Standard – auf den verschiedensten Systemen und Compilern flächendeckend verbreiten wird.
|