Galileo Computing < openbook > Galileo 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

Download:
- ZIP, ca. 10,6 MB
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
Galileo Computing
ISBN 978-3-8362-1411-7
Pfeil 14 Dynamische Speicherverwaltung
Pfeil 14.1 Das Speicherkonzept
Pfeil 14.2 Speicherallokation mit »malloc()«
Pfeil 14.3 Das NULL-Mysterium
Pfeil 14.3.1 NULL für Fortgeschrittene
Pfeil 14.3.2 Was jetzt – NULL, 0 oder \0 ... ?
Pfeil 14.3.3 Zusammengefasst
Pfeil 14.4 Speicherreservierung und ihre Probleme
Pfeil 14.5 »free()« – Speicher wieder freigeben
Pfeil 14.6 Die Freispeicherverwaltung
Pfeil 14.6.1 Prozessinterne Freispeicherverwaltung
Pfeil 14.7 Dynamische Arrays
Pfeil 14.8 Speicher dynamisch reservieren mit »realloc()« und »calloc()«
Pfeil 14.9 Speicher vom Stack anfordern mit »alloca()« (nicht ANSI C)
Pfeil 14.10 »free()« – Speicher wieder freigeben
Pfeil 14.11 Zweidimensionale dynamische Arrays
Pfeil 14.12 Wenn die Speicherallokation fehlschlägt
Pfeil 14.12.1 Speicheranforderung reduzieren
Pfeil 14.12.2 Speicheranforderungen aufteilen
Pfeil 14.12.3 Einen Puffer konstanter Größe verwenden
Pfeil 14.12.4 Zwischenspeichern auf Festplatte vor der Allokation
Pfeil 14.12.5 Nur so viel Speicher anfordern wie nötig


Galileo Computing - Zum Seitenanfang

14.8 Speicher dynamisch reservieren mit »realloc()« und »calloc()« topZur vorigen Überschrift

In der Headerdatei <stdlib.h> sind noch zwei weitere Funktionen zum dynamischen Reservieren von Speicher deklariert. Hier sehen Sie die Syntax zu diesen Funktionen:

void *calloc(size_t anzahl, size_t groesse);
void *realloc(void *zgr, size_t neuegroesse);

Die Funktion calloc() ist der Funktion malloc() sehr ähnlich, nur dass es bei der Funktion calloc() nicht einen, sondern zwei Parameter gibt. Im Gegensatz zu malloc() können Sie mit calloc() noch die anzahl von Speicherobjekten angeben, die reserviert werden soll. Wird z. B. für 100 Objekte vom Typ int Speicherplatz benötigt, so erledigen Sie dies mit calloc() folgendermaßen:

int *zahlen;

zahlen = calloc(100,sizeof(int));

Außerdem werden mit der Funktion calloc() alle Werte des allozierten Speicherbereichs automatisch mit dem Wert 0 initialisiert. Bei malloc() hat der reservierte Speicherplatz zu Beginn einen undefinierten Wert. Allerdings können Gleitpunkt- und Zeiger-Nullen auch ganz anders dargestellt werden, weshalb man sich auf solchen Feldern nicht auf die Nullen verlassen kann. Gleichwertig zu calloc() verhält sich außerdem folgendes Code-Konstrukt mit malloc():

ptr = calloc(100, sizeof(int));

// Alternative dafür mit malloc(); erfüllt denselben Zweck
ptr = malloc(100 * sizeof(int));
memset(ptr, 0, 100 * sizeof(int));

Da calloc() außer den beiden eben genannten Unterschieden genauso funktioniert wie die Funktion malloc(), gehe ich nicht mehr näher darauf ein.

Interessanter ist dagegen die dynamische Speicherreservierung mit der Funktion realloc(). Mit dieser Funktion ist es möglich, während des laufenden Programms so viel Speicher zu reservieren, wie Sie benötigen. Des Weiteren können Sie sich darauf verlassen, dass ein neuer Pool mit malloc() erstellt wird und die ganzen Ergebnisse herüberkopiert werden, wenn im aktuellen Speicherblock nicht mehr genügend freier Speicher vorhanden ist.

Mit realloc() ist es noch einfacher, z. B. dynamische Arrays zu programmieren. Die Anfangsadresse des dynamischen Arrays ist diejenige, auf die der Zeiger (zgr) zeigt. Der Parameter neuegroesse dient dazu, einen bereits zuvor allozierten Speicherplatz auf neuegroesse Bytes zu vergrößern. Die Funktion realloc() ermöglicht es auch, den Speicherplatz zu verkleinern. Dazu wird einfach der hintere Teil des Speicherblocks freigegeben, während der vordere Teil unverändert bleibt. Bei einer Vergrößerung des Speicherplatzes mit realloc() behält der vordere Teil auf jeden Fall seinen Wert, und der neue Teil wird einfach hinten angehängt. Dieser angehängte Wert ist aber wie bei malloc() undefiniert. Hier sehen Sie ein kleines Beispiel dafür, wie ein Array mit der Funktion realloc() dynamisch erstellt wird:

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

int main(void) {
   int n=0, max=10, z,i;
   int *zahlen=NULL;

   /* Wir reservieren Speicher für 10 int-Werte mit calloc. */
   zahlen = calloc(max, sizeof(int));
   if(NULL == zahlen) {
      printf("Kein virtueller RAM mehr vorhanden ... !");
      return EXIT_FAILURE;
   }
   printf("Zahlen eingeben --- Beenden mit 0\n");
   /* Endlossschleife */
   while(1) {
      printf("Zahl (%d) eingeben : ", n+1);
      scanf("%d", &z);
      if(z==0)
         break;
      /* Reservierung von Speicher während der Laufzeit
       * des Programms mit realloc */
       if(n >= max) {
          max += max;
          zahlen = realloc(zahlen,max*sizeof(int));
          if(NULL == zahlen) {
             printf("Kein virtueller RAM mehr vorhanden ... !");
             return EXIT_FAILURE;
          }
          printf("Speicherplatz reserviert "
                 " (%d Bytes)\n", sizeof(int) * max);
       }
       zahlen[n++] = z;
   }
   printf("Folgende Zahlen wurden eingegeben ->\n\n");
   for(i = 0; i < n; i++)
      printf("%d ", zahlen[i]);
   printf("\n");
   free(zahlen);
   return EXIT_SUCCESS;
}

Den benötigten Speicherbedarf könnten Sie in diesem Beispiel auch einzeln allozieren. Die einfache Anwendung dieser Funktion soll nicht darüber hinwegtäuschen, dass auch hier erst der alte Speicherbereich temporär zwischengespeichert werden muss, so wie bei der Funktion malloc(). In diesem Fall ist es aber einfacher, da Sie sich nicht mehr selbst darum kümmern müssen.

Im Beispiel wurde der Speicherplatz nach jedem erneuten Allozieren mit calloc() gleich verdoppelt (max += max). Dies ist nicht optimal. Benötigt ein Programm z. B. täglich 500 double-Werte, wäre es am sinnvollsten, erst nach 500 double-Werten neuen Speicher zu allozieren. Somit müsste das Programm nur einmal am Tag neuen Speicher bereitstellen.

Dasselbe Beispiel lässt sich recht ähnlich und einfach auch auf char-Arrays umschreiben. Das folgende Listing demonstriert die dynamische Erweiterung eines Strings:

/* dyn_string1.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUF 255

int main(void) {
   size_t len;
   char *str = NULL;
   char puffer[BUF];

   printf("Ein dynamisches char-Array für Strings\n");
   printf("Eingabe machen : ");
   fgets(puffer, BUF, stdin);
   str = malloc(strlen(puffer)+1);
   if(NULL == str) {
      printf("Kein virtueller RAM mehr vorhanden ... !");
      return EXIT_FAILURE;
   }
   strcpy(str, puffer);
   printf("Weitere Eingabe oder beenden mit \"END\"\n>");
   /* Endlossschleife */
   while(1) {
      fgets(puffer, BUF, stdin);
      /* Abbruchbedingung */
      if(strcmp(puffer,"end\n")==0 || strcmp(puffer,"END\n")==0)
         break;
       /* aktuelle Länge von str zählen für realloc */
       len = strlen(str);
       /* neuen Speicher für str anfordern */
       str = realloc(str,strlen(puffer)+len+1);
       if(NULL == str) {
          printf("Kein virtueller RAM mehr vorhanden ... !");
          return EXIT_FAILURE;
       }
       /* Hinten anhängen */
       strcat(str, puffer);
   }
   printf("Ihre Eingabe lautete: \n");
   printf("%s", str);
   free(str);
   return EXIT_SUCCESS;
}

Beim char-Array läuft es so ähnlich ab wie schon im Beispiel mit den int-Werten zuvor. Sie müssen allerdings immer darauf achten, dass bei erneuter Speicheranforderung mit realloc() das Stringende-Zeichen berücksichtigt wird (+1). Ansonsten ist der Vorgang recht simpel: String einlesen, Zeichen zählen, erneut Speicher reservieren und hinten anhängen.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






<< 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: Einstieg in C++






 Einstieg in C++


Zum Katalog: C++ von A bis Z






 C++ von A bis Z


Zum Katalog: C/C++






 C/C++


Zum Katalog: Shell-Programmierung






 Shell-Programmierung


Zum Katalog: Linux-UNIX-Programmierung






 Linux-UNIX-
 Programmierung


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Katalog: Ubuntu GNU/Linux






 Ubuntu GNU/Linux


Zum Katalog: Coding for Fun







 Coding for Fun 


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Galileo Press 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.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de