Malloc ein 3-dimensionales Array in C?
Bin ich der übersetzung einige MATLAB-code in C und Skript-ich bin die Konvertierung macht starken Gebrauch von der 3D-arrays mit 10*100*300 komplexe Einträge. Die Größe des Arrays hängt auch von den sensor-Eingang, im Idealfall sollte das array werden dynamisch zugewiesen. Bisher habe ich versucht, zwei Ansätze, der erste einer flachen 1D-array entlang der Linien von
value = array[x + (y*xSize) + (z*ySize*xSize)]
Das tut weh, mein Hirn zu benutzen. Ich habe auch versucht ein array von einem array von Zeigern
int main () {
int ***array = malloc(3*sizeof(int**));
int i, j;
for (i = 0; i < 3; i++) {
*array[i] = malloc(3*sizeof(int*));
for (j = 0; j < 3; j++) {
array[i][j] = malloc(3*sizeof(int));
}
}
array[1][2][1] = 10;
return 0;
}
Gibt ein seg-fault, wenn ich versuche der Zuordnung der Daten.
In einer perfekten Welt würde ich gerne die zweite Methode verwenden, mit der array-notation für sauberere, einfachere Programmierung. Gibt es einen besseren Weg, um dynamisch zuweisen einer drei-dimensionales array in C?
InformationsquelleAutor der Frage Mike | 2010-02-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde mich für die erste option (die einzige 1D-array) als es wird Ihnen einen einzigen block des Speichers zu spielen, anstatt potenziell Tausende von fragmentierten Speicher-Blöcke
Wenn ein Zugriff auf das richtige array-element ist dabei Ihr Kopf, obwohl, ich würde schreiben Sie eine utility-Methode zum konvertieren von x -, y -, z-Positionen zu einem offset in dem 1D array
InformationsquelleAutor der Antwort tim_yates
Wie schon andere gesagt haben, ist es wohl besser zu reservieren, einen zusammenhängenden Speicherblock, und dann herauszufinden, die Indizierung selbst. Sie können eine Funktion schreiben, die dies tun, wenn Sie wollen. Aber da Sie scheinen daran interessiert zu wissen, wie man mit der mehrere
malloc()
Fall, hier ist ein Beispiel:Zunächst definiere ich eine Funktion
free_data()
befreit, die eineint ***
mitxlen
undylen
wie die ersten beiden dimension-Größen. Wir brauchen nicht einezlen
parameter wiefree()
nicht die Länge der Zeiger freigegeben wird.Die Funktion durchläuft in einer Schleife die Zeiger
data
, findet heraus, dass diei
thint **
Zeigerdata[i]
. Dann, für einen bestimmtenint **
Zeiger, Schleifen über, herauszufinden, diej
thint *
imdata[i][j]
, und befreit es. Es muss auch freidata[i]
sobald es befreit hat, alledata[i][j]
, und schließlich muss freidata
selbst.Nun die Zuordnung Funktion. Die Funktion ist ein bisschen kompliziert, durch Fehler zu überprüfen. Insbesondere, da es
1 + xlen + xlen*ylen
malloc
ruft, wir müssen in der Lage sein zu handhaben, ein Ausfall in einem dieser Aufrufe, und befreie alle die Erinnerung, die wir reserviert, so weit. Dinge einfacher zu machen, wir verlassen uns auf die Tatsache, dassfree(NULL)
ist no-op, so setzen wir alle der Zeiger auf einem bestimmten Niveau gleichNULL
bevor wir versuchen, ordnen Sie, so dass, wenn ein Fehler passiert, können wir kostenlos alle Zeiger.Andere als die, die Funktion ist einfach genug. Wir zuerst Speicherplatz für
xlen
int **
Werte, dann für jedes dieserxlen
Zeiger, die wir Speicherplatz reservieren fürylen
int *
Werte, und dann für jede dieserxlen*ylen
Zeiger, die wir Speicherplatz reservieren fürzlen
int
Werte, so dass wir insgesamt Platz fürxlen*ylen*zlen
int
Werte:Beachten Sie, dass ich vereinfacht
malloc
fordert einiges: im Allgemeinen sollten Sie nicht umgewandelt den Rückgabewert vonmalloc
, und das Objekt angeben, das Sie die Zuweisung für die als Operanden zusizeof
- operator anstelle von Typ. Das machtmalloc
Anrufe einfacher zu schreiben und weniger Fehler-anfällig. Sie müssenstdlib.h
fürmalloc
.Hier ist ein test-Programm mit der oben genannten zwei Funktionen:
Verwenden Sie diese Methode, wenn Sie finden es einfacher, es zu benutzen. Im Allgemeinen langsamer als die Verwendung eines zusammenhängenden Speicherblock, aber wenn Sie feststellen, dass die Geschwindigkeit OK ist mit dem obigen Schema, und wenn es macht das Leben leichter, Sie können es weiterhin benutzen. Auch wenn Sie es nicht verwenden, es ist schön zu wissen, wie eine solche Regelung funktionieren.
InformationsquelleAutor der Antwort Alok Singhal
Gibt es keine Möglichkeit in C89 zu tun, was Sie verlangen, weil ein array-Typ in C kann nur angegeben werden, mit compile-Zeit bekannten Werten. Also, um zu vermeiden, dass der mad die dynamische Zuweisung, Sie haben zu stick auf den eindimensionalen Weg. Sie können eine Funktion verwenden, um diesen Prozess zu erleichtern
In C99 können Sie ein gewöhnliches array-syntax, auch wenn die Dimensionen runtime-Werte:
Jedoch, es funktioniert nur mit lokalen nicht-statischen arrays.
InformationsquelleAutor der Antwort Johannes Schaub - litb
Sind Sie sicher, dass Sie verwenden müssen
malloc
? C ermöglicht die Erstellung von multidimentional-arrays nativ:Oder verwenden Sie
malloc
in der folgenden Weise:InformationsquelleAutor der Antwort Dims
Oh, ich hasse malloc array allocation ^^
Hier ist eine richtige version, im Grunde war es nur eine falsche Linie:
InformationsquelleAutor der Antwort AndiDog
Auf diese Weise nehmen Sie nur 1 block von Speicher und die dynamische array verhält sich wie die statische (d.h. gleicher Speicher Kontiguität).
Sie können auch den freien Speicher mit einem einzigen free(array), wie es bei herkömmlichen 1-D arrays.
InformationsquelleAutor der Antwort Alberto
Über den segfault,
Ich bin mir ziemlich sicher, dass jemand darauf hingewiesen hat, aber nur für den Fall,
es gibt einen zusätzlichen '*' in der ersten Zeile und der ersten for-Schleife
versuchen Sie Folgendes:
InformationsquelleAutor der Antwort Malcolm McCullough
Hoffe, das wird dir helfen!!!!
Beim zuweisen von Speicher für 2D-array innerhalb von 3D-array, weisen Sie den zugewiesenen Arbeitsspeicher auf array[i] und nicht *array[i] und das funktioniert ohne seg-fault.
Hier ist Ihr Programm
}
InformationsquelleAutor der Antwort Quref
Unten den Code für den 3d-Speicher-Zuweisungen:
InformationsquelleAutor der Antwort ashutosh
Werden Sie zwingen, sich selbst in Wahrnehmung dieser als zwei grundsätzlich verschiedene Möglichkeiten, um zu reservieren ein 3D-array. Diese Wahrnehmung wird noch verstärkt durch zwei endgültige Differenzierung details: 1) die zweite Methode verwendet mehrere Ebenen von Dereferenzierung Zugriff auf die eigentlichen Elemente, 2) die zweite Methode weist die untere Ebene 1D-arrays unabhängig.
Aber warum genau willst du darauf bestehen, auf der Zuweisung von der unteren Ebene 1D-arrays unabhängig? Sie haben nicht zu tun. Und wenn Sie das berücksichtigen, sollten Sie erkennen, dass es eine Dritte Methode der Aufbau Ihrer 3D-array
Wenn man sich diese Verrechnung eng, Sie sollten sehen, dass am Ende das ist so ziemlich der gleiche wie deiner zweiten Methode: man baut ein drei-level-array-Struktur durch die Verwendung von intermediate-Zeiger, die auf jeder Ebene der Dereferenzierung. Der einzige Unterschied ist, dass es vor-reserviert Speicher für jede Ebene der Dereferenzierung zusammenhängend, die "in einem Schuss", vorher, statt mehreren sich wiederholenden
malloc
Anrufe. Den folgenden Zyklus einfach verteilt, pre-allocated memory unter den sub-arrays (d.h. es wird einfach initialisiert den Zeiger).Jedoch, wenn man sich noch näher, werden Sie auch feststellen, dass das aktuelle array-element Speicher (die
int
s, speichern der tatsächlichen Werte) zugeordnet sind, in genau der gleichen Weise, wie Sie es in Ihrem ersten Methode:malloc(3 * 3 * 3 * sizeof(int));
- als eine einfache Wohnung zusammenhängenden array.Nun, wenn Sie denken, Sie sollten erkennen, dass diese Dritte Methode ist nicht viel anders als Ihr Erster. Beide verwenden ein flaches array von Größe
xSize * ySize * zSize
die Daten zu speichern. Der einzige wirkliche Unterschied hier ist die Methode, die wir verwenden, um die Berechnung des index für den Zugriff auf diese Daten flat. In der ersten Methode würden wir die Berechnung der index on-the-fly alsin der Dritten Methode, die wir im Voraus berechnen die Zeiger auf array-Elemente im Voraus, mit im wesentlichen die gleiche Formel, speichern der im Voraus berechneten Ergebnisse in zusätzlichen arrays und rufen Sie Sie später über die "Natürliche" array syntax
Hier stellt sich die Frage, ob diese pre-Berechnung lohnt sich der extra-Aufwand und extra Speicher. Die Antwort ist: in der Regel Nein, es ist nicht. Durch die Ausgaben dieser zusätzliche Speicher, den Sie nicht ernten, keine nennenswerte performance-Vorteile (die Chancen sind es wird Ihr code langsamer).
Die einzige situation, wo Ihr die zweite Methode ist vielleicht auch eine überlegung Wert ist, wenn man es mit wirklich gezackt/ausgefranste array: eine sparse-multi-dimensionales array mit einigen sub-arrays Teile fehlen/nicht oder mit reduzierter Größe. Zum Beispiel, wenn einige 1D-oder 2D-sub-arrays des 3D-array bekannt sind, enthalten nur Nullen, Sie entscheiden könnten, nicht speichern Sie Sie im Speicher und setzen Sie den entsprechenden Zeiger auf null. Dies würde bedeuten verwenden die zweite Methode, wobei die sub-arrays zugeordnet sind (oder nicht zugewiesen) unabhängig. Wenn die Daten groß ist der daraus resultierende memory-Einsparungen könnte es Wert sein.
Beachten Sie auch, dass, wenn wir reden über arrays mit 3 und mehr Dimensionen, die erste/zweite/Dritte allocation-Methoden können zusammen verwendet werden, gleichzeitig auf verschiedenen Ebenen der Dereferenzierung. Sie entscheiden könnten, zu implementieren 2D-arrays mithilfe der ersten Methode und dann kombinieren Sie zu einem 3D-array mit der zweiten Methode.
InformationsquelleAutor der Antwort AnT
hinzufügen #include "stdlib.h" und entfernen Sie den * aus *array[i] und es läuft beim kompilieren des gcc 4.4.1 auf Ubuntu
auch, wenn Sie hinzufügen von print-Anweisungen finden Sie Ihre Fehler schneller
InformationsquelleAutor der Antwort Paul
InformationsquelleAutor der Antwort Vivek Patel
Sollte dies funktionieren, Sie sind nicht typecasting der Rückgabewert von malloc
Funktionierenden Link: http://ideone.com/X2mcb8
InformationsquelleAutor der Antwort bhargav22