Verwendung von malloc zur Zuweisung von mehrdimensionalen Arrays mit unterschiedlichen Zeilenlängen

Lesezeit: 4 Minuten

Benutzeravatar von asel
assel

Ich habe folgendes C Code:

int *a;
size_t size = 2000*sizeof(int);
a = malloc(size);

was gut funktioniert. Aber wenn ich folgendes habe:

char **b = malloc(2000*sizeof *b);

wo jedes Element von b hat eine andere Länge.

Wie ist es möglich, dasselbe für zu tun b wie ich für a; dh der folgende Code würde richtig halten?

char *c;
size_t size = 2000*sizeof(char *);
c = malloc(size);

Benutzeravatar von Nikolai Fetissov
Nikolai Fetissov

Zuerst müssen Sie ein Array von Zeigern wie zuweisen char **c = malloc( N * sizeof( char* ))und weisen Sie dann jeder Zeile einen separaten Aufruf von zu mallocwahrscheinlich in der Schleife:


/* N is the number of rows  */
/* note: c is char** */
if (( c = malloc( N*sizeof( char* ))) == NULL )
{ /* error */ }

for ( i = 0; i < N; i++ )
{
  /* x_i here is the size of given row, no need to
   * multiply by sizeof( char ), it's always 1
   */
  if (( c[i] = malloc( x_i )) == NULL )
  { /* error */ }

  /* probably init the row here */
}

/* access matrix elements: c[i] give you a pointer
 * to the row array, c[i][j] indexes an element
 */
c[i][j] = 'a';

Wenn Sie die Gesamtzahl der Elemente kennen (z N*M) können Sie dies in einer einzigen Zuordnung tun.

  • Wenn Sie N zuordnenM Bytes in einer einzigen Operation, dann füllen Sie alle c[i]s manuell: c[i] = p + Mich;

    – Tadeusz A. Kadłubowski

    28. Dezember 2009 um 18:28 Uhr

  • Das hängt vom Typ des c ab – wenn es char** ist, dann ja, wenn es char* ist, dann ändert sich die Indizierung: element[i][j] ~ c[i*M + j].

    – Nikolai Fetissov

    28. Dezember 2009 um 18:30 Uhr

  • @Nikolai N Fetissov, es gibt viele Mallocs im Code, wie kann das alles befreit werden? indem Sie auch for-Schleifen verwenden?

    – e19293001

    24. Oktober 2011 um 8:02 Uhr

  • @e19293001 ja, eins free für jeden malloc. Die müsstest du durchschleifen char* Variablen, die sie freigeben, und dann die freigeben char**.

    – erickrf

    8. Juni 2012 um 18:27 Uhr

  • Ich habe dasselbe in einem Buch gesehen, in dem stand: “… Speicher ist nicht garantiert zusammenhängend.”?

    – dumm3

    5. Dezember 2017 um 20:29 Uhr

Die typische Form für die dynamische Zuordnung eines NxM-Arrays vom Typ T ist

T **a = malloc(sizeof *a * N);
if (a)
{
  for (i = 0; i < N; i++)
  {
    a[i] = malloc(sizeof *a[i] * M);
  }
}

Wenn jedes Element des Arrays eine andere Länge hat, ersetzen Sie M durch die entsprechende Länge für dieses Element; zum Beispiel

T **a = malloc(sizeof *a * N);
if (a)
{
  for (i = 0; i < N; i++)
  {
    a[i] = malloc(sizeof *a[i] * length_for_this_element);
  }
}

  • Wenn ich die Gesamtzahl der Ints habe, die ich haben werde, aber nicht, wie viele davon in jedes Array gehen, wie soll ich vorgehen?

    – Diätspeck

    15. September 2014 um 23:01 Uhr

  • Sehr klare Antwort, danke! Könnten Sie auch eine Beschreibung hinzufügen, in welcher Reihenfolge richtig free der zugewiesene Speicher?

    – Kagaratsch

    18. Februar 2018 um 17:03 Uhr

  • @Kagaratsch: Im Allgemeinen kostenlos in der umgekehrten Reihenfolge, die Sie zugewiesen haben – dh jeweils kostenlos a[i] erst dann frei a.

    – Johannes Bode

    18. Februar 2018 um 17:59 Uhr

Rameshs Benutzeravatar
Ramesh

Äquivalente Speicherzuweisung für char a[10][20] wäre wie folgt.

char **a;

a=malloc(10*sizeof(char *));

for(i=0;i<10;i++)
    a[i]=malloc(20*sizeof(char));

Ich hoffe, das sieht einfach verständlich aus.

Der andere Ansatz wäre, einen zusammenhängenden Speicherblock zuzuweisen, der einen Header-Block für Zeiger auf Zeilen sowie einen Body-Block zum Speichern tatsächlicher Daten in Zeilen umfasst. Markieren Sie dann einfach den Speicher, indem Sie die Adressen des Speichers im Körper den Zeigern im Header auf Zeilenbasis zuweisen. Es würde wie folgt aussehen:

int** 2dAlloc(int rows, int* columns) {    
    int header = rows * sizeof(int*);

    int body = 0;
    for(int i=0; i<rows; body+=columnSizes[i++]) {  
    }
    body*=sizeof(int);

    int** rowptr = (int**)malloc(header + body);

    int* buf  = (int*)(rowptr + rows);
    rowptr[0] = buf;
    int k;
    for(k = 1; k < rows; ++k) {
        rowptr[k] = rowptr[k-1] + columns[k-1];
    }
    return rowptr;
}

int main() {
    // specifying column amount on per-row basis
    int columns[] = {1,2,3};
    int rows = sizeof(columns)/sizeof(int);
    int** matrix = 2dAlloc(rows, &columns);

    // using allocated array
    for(int i = 0; i<rows; ++i) {
        for(int j = 0; j<columns[i]; ++j) {
            cout<<matrix[i][j]<<", ";
        }   
            cout<<endl;
    }

    // now it is time to get rid of allocated 
    // memory in only one call to "free"
    free matrix;
}

Der Vorteil dieses Ansatzes ist das elegante Freigeben von Speicher und die Fähigkeit, eine Array-ähnliche Notation zu verwenden, um auf Elemente des resultierenden 2D-Arrays zuzugreifen.

Benutzeravatar von plinth
Sockel

Wenn jedes Element in b unterschiedliche Längen hat, müssen Sie so etwas tun:

int totalLength = 0;
for_every_element_in_b {
    totalLength += length_of_this_b_in_bytes;
}
return malloc(totalLength);

  • Es weist einem eindimensionalen Array von char*-Zeigern keinen Speicher zu.

    – Tadeusz A. Kadłubowski

    28. Dezember 2009 um 18:29 Uhr

Benutzeravatar von zdav
zdav

Ich denke, ein 2-Schritt-Ansatz ist am besten, weil c 2-d-Arrays nur ein Array von Arrays sind. Der erste Schritt besteht darin, ein einzelnes Array zuzuweisen, dann eine Schleife durchzugehen und dabei Arrays für jede Spalte zuzuweisen. Dieser Artikel gibt gute Details.

  • Es weist einem eindimensionalen Array von char*-Zeigern keinen Speicher zu.

    – Tadeusz A. Kadłubowski

    28. Dezember 2009 um 18:29 Uhr

Benutzeravatar von sigjuice
Sigisaft

Dynamische 2-D-Array-Speicherzuweisung

int **a,i;

// for any number of rows & columns this will work
a = malloc(rows*sizeof(int *));
for(i=0;i<rows;i++)
    *(a+i) = malloc(cols*sizeof(int));

1415870cookie-checkVerwendung von malloc zur Zuweisung von mehrdimensionalen Arrays mit unterschiedlichen Zeilenlängen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy