Anfang zurück vorwärts Ende
ANSI C - Ein Programmierkurs - Teil XIII
assert.h
Die Includedatei assert.h definiert das Makro assert, mit dem sich Testpunkte
in einem Programm einfügen lassen. Als Parameter bekommt das Makro einen
Ausdruck. Hat der Ausdruck den Wert 0, dann wird das Programm angehalten
und eine Fehlermeldung ausgegeben, die folgendem Formatstring entspricht:
"\nAssertion failed: %s, file %s, line %d\n"
|
Der erste Platzhalter gibt den Ausdruck wieder, den assert prüfen soll.
Der Dateiname und die Zeilennummer werden durch den die Makros ./c-kurs.wml
und 4757 des Preprozessors gesetzt.
Ist der Makroname NDEBUG (no debugging) definiert, wird das assert-Makro ignoriert.
Damit können durch assert Überprüfungen während der Entwicklung gemacht
werden. Bei der Programm-Version für die Auslieferung wird
durch Definition von NDEBUG die Überprüfung ausgeschaltet, ohne dass das
Makro assert aus dem Quelltext entfernt werden muss.
Beim Folgenden Beispiel wird mittels assert überprüft, ob der
stream auch wirklich ungleich NULL ist. Ist er NULL, dann ist
er mit Sicherheit nicht gültig, unser Ausdruck liefert einen Wert von
0 (Falsch) und das Programm wird angehalten. Schreiben Sie ein kleines
Programm, das diese Funktion enthält und übergeben Sie einmal einen
gültigen stream und einmal NULL. Dann versuchen Sie beides
nochmals, nachdem Sie vor der Includeanweisung für assert.h
die Zeile
eingefügt haben. Für TC/PC gibt es in den Optionen für den Compiler
das Editfeld define Macro, das auch dazu benutzt werden kann,
NDEBUG für die Releaseversion zu definieren.
int WriteInFile(FILE *stream)
{
assert(stream!=NULL);
fputs("Hallo Welt",stream);
}
|
stdarg.h
In der Datei stdarg.h sind Funktionen für die Behandlung von variablen
Parameterlisten definiert, wie sie z.B. die printf-Funktion benutzt.
- void va_start(va_list ap, parmN)
- Mit dem Makro va_start initialisiert man die Bearbeitung. Dazu übergibt
man eine Variable vom Typ va_list, die dazu dient, die Parameter der
Reihe nach abzuarbeiten, und den letzten Parameter, der einen Namen
trägt.
- #define va_arg(ap, type) (*((type *)(ap))++)
- Das Makro va_arg bekommt die Variable vom Typ va_list und den Datentyp
des nächsten Parameters und liefert den Parameter. Durch eine Folge
von va_arg-Aufrufen kann man der Reihe nach jeden Parameter abarbeiten.
- #define va_end(ap)
- Sind alle Parameter abgearbeitet worden, muss vor Verlassen der
Funktion dieses Makro aufgerufen werden.
Um mit variablen Parameterlisten sinnvoll umzugehen, muss die Funktion
erkennen können, welche Parameter folgen. Bei den formatierten Ausgaben
(printf...) erfolgt dies durch die Platzhalter im Formatstring.
void Test(int x,...)
{
va_list ap;
int i;
puts("va_arg - Test");
va_start(ap, x);
for (i = 0; i < x; i++)
{
printf("Parameter %d hat den Wert %d\n", i, va_arg(ap,int) + 2);
}
}
int main(void)
{
Test(1,34);
Test(3,34,42,65);
}
|
setjmp.h
Die Definitionen aus setjmp.h erlauben es, den normalen Ablauf eines
Programms zu umgehen. Damit wird üblichereise im Fehlerfall direkt aus tief
verschachtelten Funktionsaufrufen zurückgesprungen. Leider wird hierdurch
der Programmablauf etwas durchbrochen. Bei einer guten Aufteilung eines
Programms auf Module und Bibliotheken, die auch allgemeingültig verwendbar
sind, sollten die Funktionen der Module sich geordnet beenden und einen
entsprechenden Returnwert liefern.
- void longjmp(jmp_buf jmp_buffer, int return_value);
- Mit dieser Funktion stellt man den Zustand wieder her, der mit setjmp
gespeichert wurde. Die Programmausführung geht dann so weiter, als wurde
setjmp mit dem Returnwert return_value, der ungleich 0 sein muss, beendet.
Die Funktion, aus der setjmp aufgerufen wurde, darf noch nicht beendet
sein! Globale Variablen haben wieder den Wert von vor dem Aufruf von
setjmp, der Wert von automatischen Variablen aus der Funktion, die
setjmp aufruft, ist undefiniert.
- int setjmp(jmp_buf jmp_buffer);
- Diese Funktion speichert den aktuellen Zustand in jmp_buffer ab, um ihn
später wieder anspringen zu können. Diese Funktion liefert in diesem
Fall 0 zurück. Wenn mit longjmp zu dieser Stelle zurückgesprungen
wird, befindet man sich hinter diesem Aufruf, aber mit einem Returnwert
ungleich 0.
Damit das Verhalten etwas deutlicher wird, folgt ein kleines Beispiel:
#include <stdio.h>
#include <setjmp.h>
int i;
int main(void)
{
jmp_buf TestEnv;
i = 0;
printf("i vor setjmp = %d\n", i);
if (setjmp(TestEnv) == 0)
{
puts("direkter Aufruf");
i = 4;
printf("i vor longjmp = %d\n", i);
longjmp(TestEnv, 1);
}
else
{
puts("hierher durch Aufruf von longjmp");
printf("i nach setjmp = %d\n", i);
}
puts("Programmende");
}
|
signal.h
In der Datei signal.h sind Funktionen für Ausnahmebehandlung bzw. Exceptions
definiert. Es kann sich dabei um Fehler in der Programmausführung als auch um
Signale von einem anderen Prozeß handeln. Unter UNIX oder auch MiNT mit den
entsprechenden Tools ist es möglich, mittels kill ein solches Signal an ein
Programm zu senden.
- typedef void (*sigfunc_t)( int );
- Dies ist die Definition für einen Zeiger auf die Exceptionroutine.
- sigfunc_t signal( int sig, sigfunc_t func );
- Mit diese Funktion setzt man eine eigene Funktion für eine bestimmte
Exception. Der Parameter sig gibt an, für welche Ausnahme die Funktion
func zuständig sein soll. Entsprechende Konstanten sind in signal.h
definiert. Als Funktion kann auch SIG_DFL oder SIG_IGN angegeben werden.
SIG_DFL bedeutet, dass der Default-Handler des Systems benutzt wird.
SIG_IGN bedeutet, dass das Signal ignoriert wird.
- int raise( int sig );
- Mit dieser Funktion sendet man ein Signal an sich selbst.
time.h
In time.h sind Funktionen für den Umgang mit Datum und Uhrzeit
definiert. Einige Funktionen benutzen den Datentyp tm, der den weiter unten
aufgeführten Aufbau hat. Die Komponente tm_isdst ist positiv, wenn
Sommerzeit gilt, 0, wenn keine Sommerzeit gilt und negativ, wenn diese
Information nicht zur Verfügung steht. Die restlichen Komponenten
sollten mit dem Kommentar selbsterklärend sein.
Man muss unterscheiden, ob eine Funktion die Kalenderzeit (die z.B. keine
Zeitzonen berücksichtigt) oder die Ortszeit benutzt. Die Kalenderzeit, die
in einen Datentyp time_t geschrieben wird, ist üblicherweise die Anzahl
Sekunden seit dem 1.1.1970, also dem ersten 1. Januar seit dem Bestehen von UNIX.
struct tm
{
int tm_sec; /* Sekunden nach der vollen Minute -- [0, 59] */
int tm_min; /* Minuten nach der vollen Stunde -- [0, 59] */
int tm_hour; /* Stunden nach Mitternacht -- [0, 23] */
int tm_mday; /* Tag im Monat -- [1, 31] */
int tm_mon; /* Monate seit Januar -- [0, 11] */
int tm_year; /* Jahre seit 1900 */
int tm_wday; /* Tage seit Sonntag -- [0, 6] */
int tm_yday; /* Tage seit 1. Januar -- [0, 365] */
int tm_isdst; /* Kennzeichen für Sommerzeit */
};
|
- char *asctime( const struct tm *tblock );
- Diese Funktion erzeugt aus der Zeit in tblock eine Zeichenkette, in der
die Zeit in der Form "Sun Jan 3 15:14:13 1988\n" abgelegt ist. Wenn
dieses Format nicht erwünscht ist, kann strftime benutzt werden.
- char *ctime( const time_t *timer );
- Diese Funktion gibt die Kalenderzeit in timer als Ortszeit in einem
String aus. Damit ist die Funktion äquivalent zu
asctime(localtime(timer));
- struct tm *gmtime( const time_t *clock );
- Diese Funktion wandelt die Kalenderzeit in tp in die Coordinated
Universal Time (UTC).
- struct tm *localtime( const time_t *clock );
- Diese Funktion wandelt die Kalenderzeit in clock in die Ortszeit.
- time_t time( time_t *timer );
- Diese Funktion liefert die aktuelle Kalenderzeit. Wenn timer ungleich
NULL ist, wird der Wert auch in die Variable geschrieben, auf die timer
zeigt.
- time_t mktime( struct tm *timeptr );
- Diese Funktion wandelt die Ortszeit in timeptr in die Kalenderzeit um.
- clock_t clock( void );
- Diese Funktion liefert die Systemticks, die das Programm seit dem Start
verbraucht hat. Die Konstante CLOCKS_PER_SEC liefert die Zahl Systemticks
pro Sekunde.
- size_t strftime( char *s, size_t max_size, const char *format, const struct tm *timeptr );
- Diese Funktion wandelt die Zeit aus timeptr gemäß dem Formatstring format
in einen String um, der nach s kopiert wird. Der Parameter max_size gibt
dabei an, wieviel Zeichen s maximal fassen kann. Analog zu printf werden
gewöhnliche Zeichen nach s übernommen und Platzhalter für strftime, die
aus dem Prozentzeichen, gefolgt von einem Buchstaben, bestehen, werden
durch den entsprechenden Wert aus der Struktur timeptr ersetzt.
- double difftime( time_t time2, time_t time1 );
- Diese Funktion liefert die Differenz von time2-time1 in Sekunden.
Platzhalter für strftime
- [%a] abgekürzter Wochentag
- [%A] ausgeschriebener Wochentag
- [%b] abgekürzter Monatsname
- [%B] voller Monatsname
- [%c] Datum und Uhrzeit
- [%d] Tag im Monat (1-31)
- [%H] Stunde (0-23)
- [%I] Stunde (0-12)
- [%j] Tag im Jahr (1-366)
- [%m] Monat (1-12)
- [%M] Minute (00-59)
- [%p] AM/PM
- [%S] Sekunde (00-59)
- [%w] Wochentag (0-6)
- [%W] Woche im Jahr (0-52)
- [%x] lokale Datumsdarstellung
- [%X] lokale Zeit-Darstellung
- [%y] Jahr ohne Jahrhundert (0-99)
- [%Y] Jahr mit Jahrhundertangabe
- [%Z] Name der Zeitzone (z.B. MEZ)
- [%%] das '%'-Zeichen
limits.h
In der Datei limits.h sind die Grenzen von Datentypen definiert, also den
kleinsten und den größten Wert, den ein Datentyp in dieser Implementierung
aufnehmen kann.
#define CHAR_BIT 8
#define SCHAR_MIN -128
#define SCHAR_MAX 127
#define UCHAR_MAX 255U
#define CHAR_MIN -128
#define CHAR_MAX 127
#define MB_LEN_MAX 1
#define SHRT_MIN -32768
#define SHRT_MAX 32767
#define USHRT_MAX 65535U
#define INT_MIN -32768
#define INT_MAX 32767
#define UINT_MAX 65535U
#define LONG_MIN -2147483648L
#define LONG_MAX 2147483647L
#define ULONG_MAX 4294967295LU
|
float.h
Die Datei floats.hbeschreibt wie limits.h die
Grenzen von Datentypen, allerdings für float- und
double-Werte.
#define FLT_ROUNDS 1
#define FLT_RADIX 2
#define FLT_MANT_DIG 24
#define FLT_DIG 6
#define FLT_MIN_EXP -125
#define FLT_MIN_10_EXP -37
#define FLT_MAX_EXP 128
#define FLT_MAX_10_EXP 38
#define FLT_EPSILON 1.192093E-07
#define FLT_MIN 1.175494E-38
#define FLT_MAX 3.402823E+38
#define DBL_MANT_DIG 64
#define DBL_DIG 19
#define DBL_MIN_EXP -16383
#define DBL_MIN_10_EXP -4932
#define DBL_MAX_EXP 16384
#define DBL_MAX_10_EXP 4932
#define DBL_EPSILON 5.421010862427522170E-0020
#define DBL_MIN 1.681051571556046753E-4932
#define DBL_MAX 1.189731495357231765E+4932
#define LDBL_MANT_DIG 64
#define LDBL_DIG 19
#define LDBL_MIN_EXP -16383
#define LDBL_MIN_10_EXP -4932
#define LDBL_MAX_EXP 16384
#define LDBL_MAX_10_EXP 4932
#define LDBL_EPSILON 5.421010862427522170E-0020
#define LDBL_MIN 1.681051571556046753E-4932
#define LDBL_MAX 1.189731495357231765E+4932
|
Der folgende, letzte Abschnitt liefert eine kurze Übersicht und Erklärung von Compiler-Optionen der verschiedenen Systeme.
Michael Bernstein |