2016-04-27 8 views
3

Jedes Mal, wenn ich den Speicher für ein 2D-Array zuweisen, erstelle ich zuerst ein Array von int** und dann mit einem für ich den Speicher für jedes Element zuweisen.Malloc ein 2D-Array in C

Zum Beispiel:

int ** arr = malloc(N*sizeof(int *)); 
for(i=0; i< N; i++) arr[i] = malloc(M*sizeof(int)); 

Wäre es nicht möglich sein, den Speicher zuordnen wie:

int ** arr = malloc(N*sizeof(int[M])); 

oder

int ** arr = malloc(sizeof(int[N][M])); 

um die for zu vermeiden?

+2

Sind Sie mit C oder C++? – NathanOliver

+0

@NathanOliver C – ninazzo

+0

Sie könnten Ihre eigene Funktion schreiben, die alles enthält, was dazu nötig ist. Ansonsten gibt es keine Syntax-Tricks, die dies ermöglichen würden. –

Antwort

7

wie folgt aus: int (*arr)[M] = malloc(sizeof(int[N][M]));

arr ist Zeiger auf int[M].

Verwendung wie arr[0][M-1];

und free(arr);

+0

Noch besser - 'int (* arr) [M] = malloc (sizeof * arr * N);'. Auf diese Weise müssen Sie den Ausdruck 'sizeof' nicht ändern, wenn sich der Typ von' arr' ändert. –

+0

@ JohnBode siehe [diese Antwort] (http://stackoverflow.com/a/32985668/971127) – BLUEPIXY

+0

Offensichtlich ist das nur ein Problem, wenn 'M' keine Kompilierzeitkonstante ist. Und selbst wenn es so ist, muss "auswerten" nicht gleichbedeutend sein mit "Dereferenzierung". Alles was "ausgewertet" werden muss, ist der * Typ * des Ausdrucks '* arr'; Es gibt keinen logischen Grund, dass 'sizeof' jemals * den arr' dereferenzieren müsste, um seinen Typ zu bestimmen. Ja, wenn Sie streng pendent sein wollen (und wer unter uns nicht ist), ist das Verhalten undefiniert, aber nur weil die Definition von "evaluate" ungenau ist. –

10

int ** arr = malloc(N*sizeof(int[M])); einfach falsch C-Code ist, wenn Sie es simulieren einmal wie dies durch die Zuweisung:

int *arr = malloc(N*M*sizeof(int)); 

Zugriff es hinzufügen von arr[i*M + j], ist dieses analoge arr[I][j] in Ihrem ersten Fall zugreifen.

+5

@Olaf Beruhige dich, es gibt kein 2D-Array, das du mit C haben kannst, das OP will einmal für einen Puffer reservieren, um NxM-Ints zu halten. – fluter

+2

Plus, es ist überhaupt nicht "veraltet", es ist etwas, was Sie heute sehen. Es hängt alles von Ihrem Anwendungsfall ab. Es ist merkwürdig, dass man eine Art Code als "veraltet" bezeichnen kann. – fluter

+0

Ich fragte nur, ob es einen Weg gab ** wie ** das, ich sagte nie, dass ** das ** der Weg war. – ninazzo

1

Sie haben einen "Zeiger auf den Zeiger". Das kann kein 2D-Array darstellen.

Die richtige Erklärung eines Zeigers auf einem 2D-Array ist

// number of elements in one row 
#define COLS 10 

// number of rows 
#define ROWS 20 

int (*array)[COLS]; // mind the parenthesis! 

Das array einen Zeiger auf Array von COLSint s macht. Der Typ ist `int (*) [COLS], btw. aber Sie brauchen den Typ nicht, siehe unten.

Um die Array zuweisen sollten Sie dann die Standardbelegung für eine 1D-Array nutzen:

array = malloc(sizeof(*array) * ROWS); // COLS is in the `sizeof` 

array = malloc(sizeof(int[ROWS][COLS])); // explicit 2D array notation 

Welcher Variante ist persönlicher Stil zu verwenden. Während die erste keine Redundanz enthält (beachten Sie, dass Sie die Deklaration von array ändern, um INNER anstelle von COLS oder den Elementtyp zu float zu verwenden). Die zweite ist auf den ersten Blick klarer, aber fehleranfälliger beim Ändern der Deklaration von array.

Um free:

free(array); 
+0

Ich wäre neugierig zu wissen, was der Einwand des Downvoters war. –

+1

@MichaelPetch: Ich auch. Aber Sie können nicht streiten mit <(Nun, Sie könnten eine Idee haben, was ich hier schreiben würde)>. – Olaf