8.4 Programmdiagnose mit assert()
Die Definition des Makros assert() (und auch static_assert; siehe Abschnitt 3.9.4, »Sicherheit beim Kompilieren mit _static_assert()«) in der Header-Datei assert.h hängt von dem Makro NDEBUG ab, das nicht von assert.h definiert wird. Wenn Sie NDEBUG definieren, werden alle im Code folgenden assert()-Makros vom Compiler ignoriert. Wichtig ist es dabei auch, dass Sie NDEBUG vor dem Inkludieren von assert() definieren. Definieren Sie NDEBUG nicht, können Sie das Makro assert() verwenden, um Ausdrücke zur Laufzeit auf logische Fehler zu testen. Ist der Ausdruck gleich 0, wird eine Fehlermeldung als Diagnose ausgegeben und das Programm mit abort() abgebrochen. Gerade wenn Sie anfangen, ein Programm zu entwickeln und zu testen, sind solche Assertionen sehr hilfreich.
Es folgt ein einfaches Beispiel, das das assert()-Makro in der Praxis demonstriert:
00 // Kapitel8/assert.c
01 #include <stdio.h>
02 #include <stdlib.h>
03 #include <math.h>
04 // #define NDEBUG
05 #include <assert.h>
06 int main(void) {
07 double x = 0.0;
08 printf("Bitte eine positive Gleitkommazahl: ");
09 if( scanf("%lf", &x) != 1 ) {
10 printf("Fehler bei der Eingabe ...\n");
11 return EXIT_FAILURE;
12 }
13 assert(x >= 0.0);
14 double dval = sqrt(x);
15 printf("%lf\n", dval);
16 return EXIT_SUCCESS;
17 }
In diesem Beispiel wird in Zeile (13) überprüft, ob die Gleitkommazahl größer bzw. gleich 0.0 ist. Solange dieser Gesamtausdruck nicht ungleich 0 ist, wird das Programm ordnungsgemäß ausgeführt. Das Programm gibt bei der Ausführung z. B. Folgendes aus:
Bitte eine positive Gleitkommazahl: 3.1
1.760682
Bitte eine positive Gleitkommazahl: -3.3
Assertion failed: file /Projects/listing007/
listing007.c, func main, line 15, x >= 0.0
abort -- terminating
*** Process returned 1 ***
Das Programm bei der Ausführung, wobei das auskommentierte NDEBUG in Zeile (04) definiert wurde:
Bitte eine positive Gleitkommazahl: -3.3
nan
assert() für die Entwicklungsphase
Der Einsatz von assert() sollte der Entwicklungsphase vorbehalten sein. Ein Anwender kann in der Regel nicht viel mit der Fehlerausgabe anfangen. Wenn Sie das Programm freigeben, sollten Sie für das Release NDEBUG definieren, wodurch jedes assert() im Programm durch ein Null-Makro ersetzt wird. Erwägen Sie auch die Verwendung von static_assert(), womit Sie eine Überprüfung bereits während der Kompilierzeit vornehmen können. static_assert() ist seit C11 dabei und wurde im Buch bereits im Abschnitt 3.9.4, »Sicherheit beim Kompilieren mit _static_assert()«, behandelt.