2016-08-13 2 views
0

Ich habe das folgende Stück Code in C:Zuweisung von Speicher für ein 3D-Array in C mit Zeigern?

double ***grid 
grid = calloc(nx, sizeof(double**)) 
for (int i = 0; i < nx; ++i) { 
    grid[i] = calloc(ny,sizeof(double*)); 
    for (int j = 0; j < ny; ++j) { 
     grid[i][j] = calloc(nz,sizeof(double)); 
    } 
} 

Was ich nicht verstehe ist, warum können wir nicht grid[i]=calloc(ny,sizeof(double**)) schreiben? Ist es nicht wahr, dass jedes Mitglied des Grids ein "Zeiger auf Zeiger" ist? Auch sollten wir nicht grid[i][j] = calloc(nz,sizeof(double*)) haben?

Der Code funktioniert gut, wenn ich grid[i][j][k] in seiner aktuellen Form verwende, aber ich bin verwirrt warum. Ich bin neu in C, also würde ich alle Arten von Erklärungen zu schätzen wissen.

EDIT: eine Zeile fehlt: grid = calloc(nx, sizeof(double**))

+1

Beginnen Sie mit einem einfacheren Beispiel: 'int * p; p = calloc (10, sizeof (int)); ' – melpomene

+0

@melpomene exellent suggestion, danke :) – secluded

+1

Der Titel ist irreführend: Der gezeigte Code ordnet ein gezacktes" 3D-Array "zu, das tatsächlich ein 1D-Array von' ist double ** 'mit Größe X, X 1D-Arrays von' double * 'mit Größe Y und Y 1D-Arrays von' double' mit Größe Z. Also gibt es hier nur 1D-Arrays, nämlich 1 + X + Y. Ein reales 3D-Array wäre wie dieses 'double array3d [X] [Y] [Z]' definiert. – alk

Antwort

1

Zuerst die erste alloc ist vermisst: grid = calloc(nx, sizeof(double **)); aber ich bin nicht sicher, dass dies der Punkt ist, da der Code nicht kompiliert selbst (fehlende Semikolon nach grid Erklärung so es muss woanders zugeordnet wurden)

Dann Ihre Frage zu beantworten, die Zuweisung eines Zeigers auf dem Objekt zurückgibt, die eine zusätzliche * fügt hinzu, aber Sie haben die Größe des Elements angeben, für calloc die Berechnungen zu machen (ny*sizeof(object))

grid[i]=calloc(ny,sizeof(double**)) 

würde funktionieren, weil die Größe des Zeigers auf den Zeiger von double ist der gleiche wie der Zeiger von double, aber es ist nicht perfekt.

wenn Sie ein Array von int, die Sie wie folgt vergeben:

int *array = calloc(ny,sizeof(int *)) 

wird es alles in Ordnung auf den meisten Plattformen arbeiten, aber wenn Sie auf einem 64-Bit-Architektur mit einem Standard-32-Bit-int (Windows 64-Bit-Box zum Beispiel, GCC 64-Bit-Compiler), da Zeiger 64 Bit sind, wird es doppelt so viel Speicher zuweisen, wie Sie wirklich brauchen. Die korrekte Syntax in diesem Fall ist:

int *array = calloc(ny,sizeof(int)) 

weil das Element ein int ist, und es gibt einen Zeiger auf int (int *)

So, jetzt, wiederkehrend, wenn Sie hinzufügen einen Stern auf die linke, Sie einen Stern auf der rechten Seite hinzufügen:

int **array = calloc(ny,sizeof(int *)) 
int ***array = calloc(ny,sizeof(int **)) 

und so weiter ...

Kleine persönliche Geschichte: Einige böse Abstürze aufgetreten sind, wenn sie von 32-Bit auf 64-Bit zurück in den Tagen der Migration, wenn die Leute zu verwenden, verwendet:

int **array = calloc(ny,sizeof(int)) // WRONG!! 

, die gearbeitet haben, während alles 32-Bit war. Wenn sizeof(int *) wegen 64-Bit-Arch auf 8 Bytes erhöht wurde, wurde nur die Hälfte der Größe zugewiesen, was zu sehr lustigen Fehlern führen konnte.

+0

"* Größe des Zeigers auf Zeiger von double ist das gleiche wie Zeiger von double *" - das ist in der Praxis oft der Fall, aber es wird nicht von C garantiert. – melpomene

+0

'int * array = calloc (ny, sizeof (int *))' funktioniert nicht garantiert: Es ist theoretisch möglich, dass 'int' größer ist als' int * '. – melpomene

+0

Sie haben Recht. Bearbeitet –

Verwandte Themen