2013-05-23 14 views
8

Ich habe eine Frage darüber, wie Speicher zugewiesen wird, wenn ich calloc. Ich habe mir this Frage angesehen, aber es behandelt nicht, wie Speicher im Falle eines dynamisch zugewiesenen zweidimensionalen Arrays zugewiesen wird.Mehrdimensionale Arrays, die über Calloc zugewiesen werden

Ich frage mich, ob es einen Unterschied in der Speicherdarstellung zwischen den folgenden drei Möglichkeiten der dynamischen Zuweisung eines 2D-Arrays gab.

Typ 1:

double **array1; 
int ii; 

array1 = calloc(10, sizeof(double *)); 
for(ii = 0; ii < 10; ii++) { 
    array1[ii] = calloc(10, sizeof(double)); 
} 
// Then access array elements like array1[ii][jj] 

Typ 2:

double **array1; 
int ii; 

array1 = calloc(10 * 10, sizeof(double *)); 
// Then access array elements like array1[ii + 10*jj] 

Typ 3:

double **array1; 
int ii; 

array1 = malloc(10 * 10, sizeof(double *)); 
// Then access array elements like array1[ii + 10*jj] 

Von dem, was ich vonverstehenund malloc, der Unterschied zwischen den letzten beiden besteht darin, dass calloc alle Elemente des Arrays auf Null setzt, während malloc nicht. Aber sind die ersten beiden Möglichkeiten, das Array äquivalent im Speicher zu definieren?

+0

Typ 2 und Typ 3 sind im Grunde die gleichen, außer Speicher wird mit "Calloc" auf 0 gesetzt. Ich weiß nicht, ob es einen wirklichen Unterschied zu Typ 1 gibt. – JBL

+0

@JBL: wirklich nur der zusätzliche Platz für die Zeiger und die Tatsache, dass die Blöcke von 10 Doubles am Ende nicht zusammenhängend sein können – Dancrumb

+0

@Dancrumb Oh tatsächlich, habe nicht daran gedacht. Guter Punkt. – JBL

Antwort

2

sind die ersten zwei Möglichkeiten, das Array im Speicher äquivalent zu definieren?

Nicht ganz. In der zweiten Art sind sie fast sicher zusammenhängend, während dies bei der ersten Art nicht sicher ist.

Typ 1: In-Memory-Darstellung wie folgt aussehen:

  +---+---+---+---+---+---+---+---+---+---+ 
    double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 
      +---+---+---+---+---+---+---+---+---+---+ 
      ^
      |------------------------------------          
       . . . . . . . . | // ten rows of doubles 
               - 
      +---+---+---+---+---+---+---+---+---+--|+ 
    double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0|| 
      +---+---+---+---+---+---+---+---+---+--|+ 
      ^ . . .      - 
      | ^^^ . . . . . | 
      | | | | ^^^^^ | 
      +-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+ 
array1[ii]| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | // each cell points to ten doubles 
      +---+---+---+---+---+---+---+---+---+---+ 
      ^
      | 
      | 
      +-|-+ 
    array1| | | 
      +---+ 

Typ 2: In-Memory-Darstellung wie folgt aussehen:

  +---+---+---+---+---+---+---+---+---+---+  +---+ 
    double| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 
      +---+---+---+---+---+---+---+---+---+---+  +---+ 
      ^^^^^^^^^^  ^
      | | | | | | | | | |   | 
      | | | | | | | | | |   | 
      +-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+-|-+  +-|-+ 
array1[ii]| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... |99 | // each cell points to one double 
      +---+---+---+---+---+---+---+---+---+---+  +---+ 
      ^
      | 
      | 
      +-|-+ 
    array1| | | 
      +---+ 
-1

In der ersten Weise ordnen Sie 10 Zeiger auf doppelte und 100 doppelte. Auf die zweite Art ordnen Sie dem Doppel 100 Zeiger zu. Der andere Unterschied besteht darin, dass Sie auf die zweite Weise einen großen Speicherblock zuweisen, so dass alle Elemente Ihres Arrays im selben Block liegen. In der ersten Weise befindet sich jede "Zeile" Ihres Arrays in einem anderen Block als die anderen. In der zweiten Möglichkeit sollte Ihr Array jedoch ein Double * statt eines Double ** sein, da Ihr Array bei dieser Art der Zuweisung nur Pointer enthält, die doppelt sind, nicht doppelt.

+0

Die ersten zwei Möglichkeiten verwenden nicht die gleiche Menge an Speicher. Die erste Methode verwendet zehnmal mehr als die ursprüngliche Größe eines Zeigers. – Dancrumb

+0

Erste Methode: 10 Zeiger, 100 Doppel, zweite Methode: 100 Zeiger, kein Doppel, ja nicht die gleiche Menge mein schlechtes. Aber die zweite Methode hat noch keine doppelte Zuweisung. –

+0

Für Korrekturen bearbeitet. –

-1

Im Fall 1 Sie machen:

array1[0] -> [memory area of 10] 
array1[1] -> [memory area of 10] ... 
array1[N] -> [memory area of 10] ... 

Hinweis: Sie nicht, dass der Speicherbereich kontinuierlich ist annehmen kann, kann es Lücken. 2

Im Fall, dass Sie machen:

array1 -> [memory area of 100] 

Der Fall 3 ist die gleiche wie bei 2, aber es ist nicht die Erinnerung zu initialisieren. Unterschied zwischen Fall 1 und 2 & 3 ist, dass im ersten Fall Sie wirklich 2D-Speicherstruktur haben. Zum Beispiel, wenn Sie die Zeilen 1 und 2 tauschen, können Sie tauschen nur die Zeiger:

help  = array1[1] 
array1[1] = array1[2] 
array1[2] = help 

Aber wenn Sie das gleiche in der 2 & 3 Fall tun wollen, müssen Sie echte Memcpy tun. Was zu verwenden? Hängt davon ab, was du tust.

Der erste Weg verwendet etwas mehr Speicher: Wenn Sie Array von 1000x10 hätten, dann würde die erste Version 1000 * 8 + 1000 * 10 * 8 (auf 64bit System) verwenden, während die 2 & 3 nur 1000 * verwenden 10 * 8.

+0

Die Fälle 2 und 3 verwenden weniger oder gleichen Speicher als die erste. – alk

+0

Sie haben absolut Recht. Das war es, was ich im letzten Absatz mit den Zahlen zu erklären versuchte, aber "Tippfehler" hatte "zweite" gesagt, wie es "zuerst" sein sollte. Ich habe den Beitrag dafür bearbeitet. – susundberg

+0

Sie wissen, dass die Fälle 2 und 3 überhaupt keine Doubles zuweisen, sondern nur Zeiger auf diese, oder? – alk

1

einfaches Beispiel

#include<stdio.h> 
#include<stdlib.h> 

int **d ; 
int sum(); 

//-----------------------------------------------    
int main(){ 

    d = (int **)calloc(3,sizeof(int)); 
    printf("\n%d",sum()); 

} 

//----------------------------------------------- 
int sum(){ 
int s = 0; 
for(int i = 0; i < 3; i++) 
    d[i] = (int *)calloc(3,sizeof(int)); 

for(int i = 0; i < 3; i++){ 
    for(int j = 0; j < 3; j++){ 
     d[i][j] = i+j; 
     s += d[i][j]; 
     printf("\n array[%d][%d]-> %d",i,j,d[i][j]); 
    } 
} 
return s; 
} 
Verwandte Themen