Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
Vorwort des Gutachters
1 Einstieg in C
2 Das erste Programm
3 Grundlagen
4 Formatierte Ein-/Ausgabe mit »scanf()« und »printf()«
5 Basisdatentypen
6 Operatoren
7 Typumwandlung
8 Kontrollstrukturen
9 Funktionen
10 Präprozessor-Direktiven
11 Arrays
12 Zeiger (Pointer)
13 Kommandozeilenargumente
14 Dynamische Speicherverwaltung
15 Strukturen
16 Ein-/Ausgabe-Funktionen
17 Attribute von Dateien und das Arbeiten mit Verzeichnissen (nicht ANSI C)
18 Arbeiten mit variabel langen Argumentlisten – <stdarg.h>
19 Zeitroutinen
20 Weitere Headerdateien und ihre Funktionen (ANSI C)
21 Dynamische Datenstrukturen
22 Algorithmen
23 CGI mit C
24 MySQL und C
25 Netzwerkprogrammierung und Cross–Plattform-Entwicklung
26 Paralleles Rechnen
27 Sicheres Programmieren
28 Wie geht’s jetzt weiter?
A Operatoren
B Die C-Standard-Bibliothek
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch
Buch: C von A bis Z

C von A bis Z
3., aktualisierte und erweiterte Auflage, geb., mit CD und Referenzkarte
1.190 S., 39,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1411-7
Pfeil 20 Weitere Headerdateien und ihre Funktionen (ANSI C)
Pfeil 20.1 <assert.h> – Testmöglichkeiten und Fehlersuche
Pfeil 20.2 <ctype.h> – Zeichenklassifizierung und Umwandlung
Pfeil 20.3 Mathematische Funktionen – <math.h>, <tgmath.h> und <complex.h>
Pfeil 20.3.1 Funktionen für reelle und komplexe Gleitpunkttypen
Pfeil 20.3.2 Funktionen nur für reelle Gleitpunkttypen
Pfeil 20.3.3 Funktionen nur für komplexe Gleitpunkttypen
Pfeil 20.3.4 Typengenerische Makros – <tgmath.h>
Pfeil 20.3.5 Gleitpunktwerte klassifizieren
Pfeil 20.3.6 Makro zum Vergleichen von reellen Zahlen
Pfeil 20.3.7 Zugriff auf die Gleitpunkt-Umgebung – <fenv.h>
Pfeil 20.4 <stdlib.h>
Pfeil 20.4.1 Programmbeendigung – »exit()«, »_exit()«, »atexit()« und »abort()«
Pfeil 20.4.2 Strings in numerische Werte konvertieren
Pfeil 20.4.3 Bessere Alternative – Strings in numerische Werte konvertieren
Pfeil 20.4.4 Zufallszahlen
Pfeil 20.4.5 Absolutwerte, der Quotient und der Rest von Divisionen
Pfeil 20.4.6 Suchen und Sortieren – »qsort()« und »bsearch()«
Pfeil 20.4.7 system()
Pfeil 20.5 <locale.h> – länderspezifische Eigenheiten
Pfeil 20.6 Nicht-lokale Sprünge – <setjmp.h>
Pfeil 20.7 <signal.h>
Pfeil 20.8 <string.h> – die »mem…«-Funktionen zur Speichermanipulation
Pfeil 20.8.1 »memchr()« – Suche nach einzelnen Zeichen
Pfeil 20.8.2 »memcmp()« – bestimmte Anzahl von Bytes vergleichen
Pfeil 20.8.3 »memcpy()« – bestimmte Anzahl von Bytes kopieren
Pfeil 20.8.4 »memmove()« – bestimmte Anzahl von Bytes kopieren
Pfeil 20.8.5 »memset()« – Speicherbereich mit bestimmten Zeichen auffüllen


Rheinwerk Computing - Zum Seitenanfang

20.6 Nicht-lokale Sprünge – <setjmp.h> topZur vorigen Überschrift

In C sind Sprünge über Funktionsgrenzen hinweg nicht erlaubt. Das heißt genau: Funktionen werden immer an den direkten Ausrufer zurückgegeben. Wenn z. B. Funktion 1 die Funktion 2 aufruft, kehrt Funktion 2 immer zuerst zur Funktion 1 zurück – eben in der umgekehrten Reihenfolge wie die einzelnen Funktionen auf (genauer: unter) dem Stack abgelegt wurden. Erst dann kann Funktion 1 zu ihrem Aufrufer zurückkehren. Ein Beispiel:

/* call_func.c */
#include <stdio.h>
#include <stdlib.h>

void func1(void);
void func2(void);
void func3(void);
void func4(void);
void func1(void) {
   printf("Funktion 1 ist aufgerufen!\n");
   func2();
}

void func2(void) {
   printf("Funktion 2 ist aufgerufen!\n");
   func3();
}

void func3(void) {
   printf("Funktion 3 ist aufgerufen!\n");
   func4();
}

void func4(void) {
   printf("Funktion 4 ist aufgerufen!\n");
}

int main(void) {
   func1();
   return EXIT_SUCCESS;
}

Das Programm ruft in der main()-Funktion zuerst func1() auf, func1() ruft anschließend func2() auf, func2() ruft danach func3() auf, und func3() ruft am Ende func4() auf. Anschließend kehren die einzelnen Funktionen wieder in der Reihenfolge func3(), func2() und func1() zur main()-Funktion zurück. Was wäre jetzt, wenn in func2() eine Berechnung durchgeführt wird und der Wert dieser Berechnung nicht mehr dem entspricht, den der Nutzer sich versprochen hat? Trotzdem werden sinnloserweise noch func3() und func4() aufgerufen und ausgeführt. Die Frage lautet also: Wie kann man z. B. von func2() zur main()-Funktion zurückspringen, die Funktionen func3() und func4() auslassen und auch nicht mehr über func1() zur main()-Funktion zurückkehren?

Abbildung 20.2 Rückkehr von Funktionen bei einem normalen Verlauf

Dafür können Sie die Funktionen der Headerdatei <setjmp.h> verwenden. Hier sehen Sie die Syntax:

#include <setjmp.h>

jmp_buf env;    // primitiver Datentyp jmp_buf

int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int wert);

Der Datentyp jmp_buf env ist eine Art Puffer, der den mit setjmp(env) eingefrorenen Programmzustand enthält und den Sie mit der Funktion longjmp(env,1) wiederherstellen können. jmp_buf enthält zum Beispiel die CPU-Registerinhalte (CS, DS, SS und ES), den Stackpointer (SP), den Instruktionspointer (IP) usw. – alle Informationen eben, die erforderlich sind, um den gleichen Zustand wiederherzustellen, der vor dem Aufruf von setjmp() vorlag.

Mit setjmp() werden, wie eben schon erwähnt, alle Informationen, die im Augenblick vorliegen, auf einen Stack gelegt. Der Aufruf von setjmp() lautet:

if(setjmp(env) == 0)

Beim ersten Aufruf von setjmp() liefert die Funktion den Wert 0 zurück. Beim zweiten Aufruf durch longjmp(env) liefert die Funktion auf jeden Fall einen Wert ungleich 0 zurück.

Mit der Funktion longjmp() kehren Sie dann an diese Programmstelle zurück, die Sie mit setjmp(env) auf dem Stack abgelegt haben. Dies geschieht mit folgendem Aufruf:

longjmp(env,1);

Nochmals alles zusammengefasst:

...
jmp_buf programmzustand;
...
if(setjmp(programmzustand) == 0)
    printf("Programmzustand auf den Stack gelegt\n");
else
    printf("Rücksprung mit longjmp erfolgt\n");
...
// viele, viele Funktionen später
longjmp(programmzustand,1);

Als Erstes legen Sie hier mit setjmp() den Programmzustand auf den Stack. Anschließend, viele Funktionen später, wird mit longjmp() dieser Zustand wiederhergestellt und springt zurück zu setjmp(). Dieses Mal ist der Rückgabewert von setjmp() aber nicht mehr 0, und daher fährt das Programm hinter der else-Anweisung fort.

Jetzt soll alles in einem Programm verwendet werden, ohne komplizierte Berechnungen oder Ähnliches. Es wird einfach abgefragt, wie viele Funktionen ausgeführt werden sollen, und das Programm springt nach der gewünschten Anzahl der Funktionen mit einem Aufruf von longjmp() zur main()-Funktion zurück:

/* setjmp.c */
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

void func1(int);
void func2(int);
void func3(int);
void func4(void);
jmp_buf env;

static int zahl;
void func1(int zahl) {
   printf("Funktion 1 ist aufgerufen!\n");
   if(zahl == 1)
      longjmp(env, 1);
   func2(zahl);
}

void func2(int zahl) {
   printf("Funktion 2 ist aufgerufen!\n");
   if(zahl == 2)
      longjmp(env, 2);
   func3(zahl);
}

void func3(int zahl) {
   printf("Funktion 3 ist aufgerufen!\n");
   if(zahl == 3)
      longjmp(env, 3);
   func4();
}

void func4(void) {
   printf("Funktion 4 ist aufgerufen!\n");
}

int main(void) {
   printf("Wie viele Funktionen sollen ausgefuehrt werden : ");
   scanf("%d",&zahl);
   if(setjmp(env) == 0)
      func1(zahl);
   else
      printf("Ruecksprung durch longjmp von Funktion %d!\n",zahl);
   return EXIT_SUCCESS;
}

Die Funktionen setjmp() und longjmp() haben übrigens nichts mit der Anweisung goto gemeinsam. Es hat sich als recht nützlich erwiesen, setjmp() und longjmp() bei Fehlerbehandlungen einzusetzen.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z

 C von A bis Z
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: C/C++






 C/C++


Zum Katalog: Einstieg in C






 Einstieg in C


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de