C Speicherzeuweisung auf Doppelzeiger eines structs funktioniert nicht.

Woodz

Lieutenant
Registriert
Apr. 2009
Beiträge
689
Hallo.
Ich habe folgendes Problem. Ich habe ein struct erzeugt und in diesem habe ich einen Doppelzeiger von Typ double.
Nun möchte ich diesem Doppelzeiger Speicher durch eine Funktion zuweisen, aber das funktioniert nicht. Da der Rückgabewert der Funktion ein Fehlercode sein soll, dachte ich mir, dass die Zuweisung auch ohne Rückgabewert funktionieren sollte. Ich übergebe der Funktion ja einen Doppelzeiger.

Naja. Hier der grobe Code:
C:
#include <stdio.h>
#include <stdlib.h>


struct dataset{
    double **data;
};


int allocate_memory(double **matrix, int rows, int cols);

int main(){

    struct dataset dd;
 
    printf("%p\n",dd.data);            // Ausgabe des Doppelzeigers vor der Zuweisung
    allocate_memory(dd.data, 5, 3);      
    printf("%p\n",dd.data);            // Ausgabe des Doppelzeigers nach der Zuweisung
   
    return 0;

}



int allocate_memory(double **matrix, int rows, int cols){

    int idx, jdx;

    matrix = (double**) calloc(rows, sizeof(double*));
    if (matrix == NULL){
        printf("Speicherfehler\n");
    }
    else{
        for (idx=0; idx<rows; idx++){
       
            matrix[idx] = (double*) calloc(cols, sizeof(double));
            if (matrix[idx] == NULL){
                printf("Speicherfehler\n");
            }
        }
    }
    printf("%p\n", matrix);            /* Ausgabe der Adresse des Doppelzeigers
                                       während der Zuweisung in der Funktion */
}

Ausgabe:
(nil)
0x5588dacaa6b0
(nil)

Wie ihr seht, besitzt der Doppelzeiger vor der Zuwesiung den Wert (nil). Nach der Zuweisung in der Funktion eine physische Adresse
und außerhalb der Funktion wieder (nil).
Wie ist das Möglich? Ich arbeite doch mit Zeigern und diese funktionieren doch immer mit "call by reference".

Beste Grüße
 
Tja, nein. Du überschreibst die Kopie des (Doppel-)Zeigers in der Methode, aber übergibst den (Doppel-)Zeiger nicht als Zeiger. Daher ist der Wert auch nur in der Funktion gültig.

Du müsstest also einen:
C:
int allocate_memory(double ***matrix, int rows, int cols){
 *matrix = ...
}

int main() {
double** matrix;
allocate_memory(&matrix, ...);
...
}
übergeben, damit du den Wert des Doppelzeigers setzen kannst.

Es gibt kein call by reference in C, dazu brauchst du einen Zeiger auf das, was du verändern willst.
 
Zuletzt bearbeitet:
Ok. D.h. ich übergebe die Adresse des Doppelzeigers der Funktion. Und innerhalb der Funktion weise ich der Adresse des Doppelzeigers über den Inhaltsoperator den Doppelzeiger auf die Matrix zu.
Ich glaube es verstanden zu haben.

Funktioniert! Danke!
 
Zuletzt bearbeitet:
Jep, vscode meckert auch jedesmal, wenn ich etwas refactoren will, und eine Variable modifiziert wird, dass es "kein call-by-reference in C gibt" und ich denke mir immer, dass es doch einfach die Adresse übergeben soll.

Andere Frage, warum überhaupt das struct? Insbesondere, da du ja doch nur ein double** bzw. dann eben ein ***double an allocate_memory übergibst. Warum dann nicht wenigstens das struct übergeben (bzw. dessen Adresse)?
 
Ich kann nur empfehlen, gerade für deinen Fall kein 2D Array zu verwenden, weil du dann für jede row eine eigene Speicheradresse bekommst - die nicht unbedingt direkt hintereinander ist.

Besser ist hier einfach nen normales array zu erstellen mit NumColumns * NumRows und einen 2D Zugriff in einen 1D Zugriff zu mappen: Index = RowIndex * NumCols + ColIndex;
 
Zurück
Oben