malloc in C, aber die Verwendung von multi-dimensionalen array-syntax
Gibt es eine Möglichkeit, malloc eine große Auswahl, aber finden Sie es mit 2D-syntax? Ich will etwas wie:
int *memory = (int *)malloc(sizeof(int)*400*200);
int MAGICVAR = ...;
MAGICVAR[20][10] = 3; //sets the (200*20 + 10)th element
UPDATE: Das war wichtig zu erwähnen: ich will nur einen zusammenhängenden block im Speicher. Ich möchte nur nicht, dass ein makro schreiben wie:
#define INDX(a,b) (a*200+b);
und verweisen dann auf meinem blob wie:
memory[INDX(a,b)];
Ich würde viel lieber:
memory[a][b];
UPDATE: ich verstehe, dass der compiler hat keine Möglichkeit zu wissen, wie es ist. Ich würde sein bereit zu liefern Sie zusätzliche Informationen, so etwas wie:
int *MAGICVAR[][200] = memory;
Nicht syntax wie diese gibt? Hinweis: der Grund, warum ich nicht einfach eine Feste Breite-array ist, dass es zu groß ist, um Platz auf dem stack.
UPDATE: OK, Jungs, ich kann dies tun:
void toldyou(char MAGICVAR[][286][5]) {
//use MAGICVAR
}
//from another function:
char *memory = (char *)malloc(sizeof(char)*1820*286*5);
fool(memory);
Ich bekomme eine Warnung, passing arg 1 of toldyou from incompatible pointer type
, aber der code funktioniert, und ich habe festgestellt, dass die gleichen Standorte zugegriffen werden. Gibt es eine Möglichkeit, dies zu tun, ohne mit einer anderen Funktion?
- Ja, das abgedeckt wurde, viele Male auf SO schon, z.B. C-Programmierung: malloc() für ein 2D-array (Verwendung von pointer-to-pointer)
- äh sorry, ich sollte sagen, dass ich nicht wollen, zu verschachtelte Zeiger. ich will einfach nur einen zusammenhängenden block von memry.
- Nach der Veröffentlichung meiner Antwort, ich hatte das "toldyou" Idee läuft in meinem Kopf herum. Ich kann mir einfach nicht vorstellen, wie dieses bisschen syntaktischer Zucker ist mehr Wert als alle Reifen müssen Sie springen durch, um es zu bekommen 😉
- heh, ich glaube es nicht, aber ich wusste nicht, dass wenn ich zuerst gepostet diese Frage!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ja, Sie können dies tun, und Nein, brauchen Sie nicht ein array von Zeigern wie die meisten der anderen Antworten sagen Sie. Die Anrufung, die Sie wollen, ist nur:
Wenn Sie möchten, deklarieren Sie eine Funktion die Rückgabe dieser Zeiger, können Sie entweder es so machen:
Oder verwenden Sie typedef, das macht es ein wenig klarer:
foo[]
in der Funktion parameter-Deklarationen ist nur syntaktischer Zucker für(*foo)
- es ist nur so, dass[]
bedeutet etwas anderes in der tatsächlichen Variablen-Deklarationen (wo es also ein array, dessen Größe wird bestimmt durch die initialiser).int (*MOREMAGICVAR)[b] = (int (*)[b]) malloc(a * b * sizeof(int));
a * sizeof MOREMAGICVAR[0]
Formulierung für die Größe, durch die Art und Weise (dh. wiederholen Sie nichtb
).[400][200]
Verwenden Sie einen Zeiger auf arrays:
Wenn zusätzliche Dereferenzierung ist kein Problem, Sie können verwenden Sie ein array von Zeigern.
Bearbeiten
Hier ist eine variation auf @Platinum Azure Antwort, dass nicht so viele Aufrufe von malloc. Neben der schnelleren Zuordnung, alle Elemente sind garantiert zusammenhängend:
In die gleiche Richtung wie ZAHNRAD Antwort, hier ist ein (ziemlich schmutziger) trick, der macht nur einen Aufruf
malloc()
:Dies füllt den ersten Teil des Puffers mit Zeiger auf jede Zeile in der sofort folgenden, zusammenhängenden array-Daten.
Edit:
Arrays und Zeiger Aussehen sehr viel die gleiche, aber der compiler behandelt Sie sehr unterschiedlich. Mal sehen, was getan werden muss, um für eine array-Indizierung und die de-Referenzierung einen Zeiger mit dem offset:
Sagen wir erklärten, eine statische Arrays (Arrays auf dem stack ist nur ein bisschen komplizierter, festen offset von einem register, aber im wesentlichen das gleiche):
static int array[10];
Und einen Zeiger:
static int* pointer;
Wir dann de-Ehrerbietung einzelnen wie folgt:
x = array[i];
x = pointer[i];
Das, was zu beachten ist, dass die Adresse des anfangs der
array
sowie, Adressepointer
(nicht deren Inhalt) sind festen im link/laden Zeit. Compiler dann macht Folgendes:array
de-Referenz:i
,array
, d.h. seine Feste Adresse, um die form der target-Speicher-Adresse,pointer
de-Referenz:i
,pointer
, d.h. die Inhalt an seine Adresse,Gleiche passiert auch bei 2D-array mit zusätzlichen Schritten der laden der zweiten index und Multiplikation mit der Reihe groß ist (das ist eine Konstante). All das ist beschlossen, zur compile-Zeit, und es gibt keine Möglichkeit der Substitution einer für den anderen zur Laufzeit.
Edit:
@caf hat hier die richtige Lösung. Es gibt einen legalen Weg innerhalb der Sprache zu index einen Zeiger als zwei-dimensionale array nach alle.
Den compiler und runtime haben keine Möglichkeit zu wissen, Ihre beabsichtigte dimension Kapazitäten mit nur einer Multiplikation in der malloc-Aufruf.
Müssen Sie mit einem Doppel-pointer, um zu erreichen, die Fähigkeit der beiden Indizes. So etwas sollte es tun:
Stellen Sie sicher, überprüfen Sie alle Ihre malloc return-Werte für die NULL gibt, der angibt, Fehler bei der Speicherzuweisung.
Arbeiten von Tim und caf s Antworten, überlasse ich dies hier für die Nachwelt:
memory
springt von 400, in der Erwägung, dass die OP angegebenen 200. (2) sollten Sie Ihre code-Anweisungen in getrennte Zeilen und Einrücken mit vier Leerzeichen am Anfang jeder Zeile, erstellen eine <pre> fixed-width-Umgebung.