Speicher für einen 2d-Vektor dynamisch reservieren

Beschreibung

Im Kapitel 4 des Skripts beschäftigen wir uns mit der dynamischen Reservierung von Speicher. Das hier aufgeführte Beispiel soll zeigen, wie dynamischer Speicher für ein zweidimensionales Feld reserviert werden kann, so dass dieses wie ein normaler 2d-Vektor angesprochen werden kann. Siehe dazu auch Abschnitt 6.1.2 im Skript.

Zu diesem Zweck wurden zwei hier Funktionen erstellt: malloc2d() reserviert den Speicher und free2d() gibt ihn wieder frei. Die Vorbereitung des 2d-Vektors erfolgt folgendermaßen:

  1. Zunächst wird Speicher für einen Zeigervektor reserviert.
  2. Danach wird Speicher für die eigentlichen Daten reserviert.
  3. Schließlich wird der Zeigervektor initialisiert.

Die Funktion malloc2d() wurde allgemein gehalten, so dass sie für beliebige Datentypen verwendet werden kann. Dies wurde erreicht, indem als dritter Parameter die Größe der Vektorelemente erwartet wird und ein Zeiger auf void zurückgegeben wird, der in den gewünschen Datentyp gewandelt werden muss.


// Dateiname: malloc2d.c
// Autor: Robert Heß & E2b
// Version: 1.2
// Datum: 28.04.2020
// Beschreibung: 2d-Vektor dynamisch reservieren

#include <stdlib.h>
#include <stdio.h>

void *malloc2d(size_t size1, size_t size2, size_t element);
void free2d(void **data);

//=============================================================================
int main()
{
    int width=23;           // Breite des Felds
    int height=34;          // Höhe des Felds
    double **field=NULL;    // Zeiger zum Ansprechen der Daten

    // 1. Schritt: Speicher 2d-Vektor reservieren
    field = (double**)malloc2d(width, height, sizeof(**field));

    // 2. Schritt: Speicher verwenden
    if(field) {
        field[2][3] = 1.234;
        printf("field[2][3]: %g\n", field[2][3]);
    }

    // 3. Schritt: Speicher freigeben
    free2d(field);

    return 0;
}

//=============================================================================
void *malloc2d(
    size_t size1,   // Größe für ersten Index
    size_t size2,   // Größe für zweiten Index
    size_t element) // Größe eines Datenelements
{
    char **data=NULL;   // Zeiger für 2d-Vektor
    size_t i;           // lokale Laufvariable

    // Parameter prüfen und Speicher für Zeigervektor reservieren
    if (size1 && size2 && element)
        data = (char**)malloc(size1*sizeof(void*));

    // Speicher für eigentliche Daten reservieren
    if (data) *data = (char*)malloc(size1*size2*element);

    // Zeigervektor initialisieren
    if (data && *data) {
        for (i = 1; i < size1; i++)
            data[i] = data[i - 1] + size2 * element;
    }

    // Sonderfall: wenn nur Zeigervektor reserviert wurde
    if (data && data[0] == NULL) {
        free(data);
        data = NULL;
    }

    return data;
}

//=============================================================================
void free2d(
    void **data)    // Zeiger für 2d-Vektor
{
    // free data
    if (data && *data) free(*data);
    if (data) free(data);
}
Seite 21