Suche…


Einführung

Arrays sind abgeleitete Datentypen, die eine geordnete Sammlung von Werten ("Elementen") eines anderen Typs darstellen. Die meisten Arrays in C haben eine feste Anzahl von Elementen eines beliebigen Typs und ihre Darstellung speichert die Elemente zusammenhängend im Speicher ohne Lücken oder Auffüllen. C erlaubt mehrdimensionale Arrays, deren Elemente andere Arrays sind, sowie Arrays von Zeigern.

C unterstützt dynamisch zugewiesene Arrays, deren Größe zur Laufzeit bestimmt wird. C99 und höher unterstützt Arrays mit variabler Länge oder VLAs.

Syntax

  • Typname [Länge]; / * Definiere ein Array von 'type' mit Namen 'name' und length 'length'. * /
  • int arr [10] = {0}; / * Definiere ein Array und initialisiere ALLE Elemente auf 0. * /
  • int arr [10] = {42}; / * Definiere ein Array und initialisiere die ersten Elemente auf 42 und den Rest auf 0. * /
  • int arr [] = {4, 2, 3, 1}; / * Definiere und initialisiere ein Array der Länge 4. * /
  • arr [n] = Wert; / * Wert an Index n setzen. * /
  • Wert = arr [n]; / * Wert an Index n abrufen. * /

Bemerkungen

Warum brauchen wir Arrays?

Arrays bieten eine Möglichkeit, Objekte zu einem Aggregat mit eigener Bedeutung zu organisieren. Zum Beispiel C - Strings sind Arrays von Zeichen ( char s) und eine Zeichenkette wie „Hallo, Welt!“ hat eine Bedeutung als Aggregat, das den Zeichen nicht individuell inhärent ist. In ähnlicher Weise werden Arrays üblicherweise verwendet, um mathematische Vektoren und Matrizen sowie Listen vieler Arten darzustellen. Ohne die Elemente gruppieren zu können, müsste man jedes einzeln ansprechen, z. B. über separate Variablen. Das ist nicht nur unhandlich, es kann nicht einfach Sammlungen unterschiedlicher Längen aufnehmen.

Arrays werden in den meisten Kontexten implizit in Zeiger konvertiert .

Außer , wenn als Operand der erscheinen sizeof - Operators, der _Alignof Operator (C2011) oder die unären & (Adresse-of) Operator oder als Stringliteral verwendet , um einen (anderen) Array zu initialisieren, wird ein Array implizit umgewandelt in ( "decays to") einen Zeiger auf sein erstes Element. Diese implizite Konvertierung ist eng an die Definition des Array-Subskriptionsoperators ( [] ) gekoppelt: Der Ausdruck arr[idx] ist als äquivalent zu *(arr + idx) . Da die Zeigerarithmetik kommutativ ist, ist *(arr + idx) auch äquivalent zu *(idx + arr) , was wiederum idx[arr] . Alle diese Ausdrücke sind gültig und werden mit demselben Wert ausgewertet, vorausgesetzt, entweder idx oder arr ist ein Zeiger (oder ein Array, das in einen Zeiger zerfällt), der andere ist eine Ganzzahl und die Ganzzahl ist ein gültiger Index für das Array auf den der Zeiger zeigt.

Beachten Sie als Sonderfall, dass &(arr[0]) äquivalent zu &*(arr + 0) , was die Vereinfachung von arr vereinfacht. Alle diese Ausdrücke sind überall dort austauschbar, wo der letzte zu einem Zeiger zerfällt. Dies drückt einfach wieder aus, dass ein Array zu einem Zeiger auf sein erstes Element zerfällt.

Im Gegensatz dazu hat das Ergebnis den Typ T (*)[N] und zeigt auf das gesamte Array, wenn der Address-of-Operator auf ein Array vom Typ T[N] angewendet wird ( dh &arr ). Dies unterscheidet sich von einem Zeiger auf das erste Array-Element zumindest in Bezug auf die Zeigerarithmetik, die in Bezug auf die Größe des Zeigetyps definiert ist.

Funktionsparameter sind keine Arrays .

void foo(int a[], int n);
void foo(int *a, int n);

Obwohl die erste Deklaration von foo für Parameter a a arrayartige Syntax verwendet, wird mit dieser Syntax ein Funktionsparameter deklariert, der diesen Parameter als Zeiger auf den Elementtyp des Arrays deklariert. Somit ist die zweite Signatur für foo() semantisch identisch mit der ersten. Dies entspricht den Zerfall von Array - Wert auf Zeiger , wo sie als Argument für einen Funktionsaufruf angezeigt wird , so dass , wenn eine Variable , und ein Funktionsparameter mit dem gleichen Array - Typ deklariert werden dann Wert, den Variable zur Verwendung in einem Funktionsaufruf als das geeignet ist , Argument, das dem Parameter zugeordnet ist.

Array deklarieren und initialisieren

Die allgemeine Syntax zum Deklarieren eines eindimensionalen Arrays lautet

type arrName[size];

wobei type ein beliebiger integrierter Typ oder benutzerdefinierte Typen wie Strukturen sein kann, ist arrName eine benutzerdefinierte Kennung und size eine Ganzzahlkonstante.

Das Deklarieren eines Arrays (in diesem Fall ein Array von 10 int-Variablen) erfolgt folgendermaßen:

int array[10];

es enthält jetzt unbestimmte Werte. Um sicherzustellen, dass es während der Deklaration null Werte enthält, können Sie Folgendes tun:

int array[10] = {0};

Arrays können auch Initialisierer enthalten. In diesem Beispiel wird ein Array von 10 int 's deklariert, wobei die ersten 3 int 's die Werte 1 , 2 , 3 enthalten.

int array[10] = {1, 2, 3};

Bei der obigen Initialisierungsmethode wird der erste Wert in der Liste dem ersten Mitglied des Arrays zugewiesen, der zweite Wert wird dem zweiten Mitglied des Arrays usw. zugewiesen. Wenn die Listengröße kleiner als die Arraygröße ist, werden wie im obigen Beispiel die verbleibenden Mitglieder des Arrays mit Nullen initialisiert. Mit der Initialisierung der benannten Liste (ISO C99) ist eine explizite Initialisierung der Array-Mitglieder möglich. Zum Beispiel,

int array[5] = {[2] = 5, [1] = 2, [4] = 9}; /* array is {0, 2, 5, 0, 9} */

In den meisten Fällen kann der Compiler die Länge des Arrays für Sie ableiten. Dies kann erreicht werden, indem Sie die eckigen Klammern leer lassen:

int array[] = {1, 2, 3}; /* an array of 3 int's */
int array[] = {[3] = 8, [0] = 9}; /* size is 4 */

Das Deklarieren eines Arrays mit der Länge Null ist nicht zulässig.

C99 C11

Arrays mit variabler Länge (kurz VLA) wurden in C99 hinzugefügt und in C11 optional gemacht. Sie sind normalen Arrays gleich, mit einem wichtigen Unterschied: Die Länge muss zum Zeitpunkt des Kompilierens nicht bekannt sein. VLAs haben eine automatische Speicherdauer. Nur Zeiger auf VLAs können eine statische Speicherdauer haben.

size_t m = calc_length(); /* calculate array length at runtime */
int vla[m];               /* create array with calculated length */

Wichtig:

VLAs sind potenziell gefährlich. Wenn das Array vla im obigen Beispiel mehr Speicherplatz auf dem Stack benötigt als verfügbar, wird der Stack überlaufen. Die Verwendung von VLAs wird daher häufig in Style-Guides, Büchern und Übungen empfohlen.

Löschen des Array-Inhalts (Nullstellen)

Manchmal ist es erforderlich, ein Array auf Null zu setzen, nachdem die Initialisierung durchgeführt wurde.

#include <stdlib.h> /* for EXIT_SUCCESS */

#define ARRLEN (10)

int main(void)
{
  int array[ARRLEN]; /* Allocated but not initialised, as not defined static or global. */

  size_t i;
  for(i = 0; i < ARRLEN; ++i)
  {
    array[i] = 0;
  }

  return EXIT_SUCCESS;
}

Eine übliche Abkürzung für die obige Schleife ist die Verwendung von memset() aus <string.h> . Wenn Sie das array wie unten gezeigt übergeben, verfällt es in einen Zeiger auf sein 1. Element.

memset(array, 0, ARRLEN * sizeof (int)); /* Use size explicitly provided type (int here). */

oder

memset(array, 0, ARRLEN * sizeof *array); /* Use size of type the pointer is pointing to. */

Wie in diesem Beispiel array ist ein Array und nicht nur einen Zeiger auf ein erstes Element des Arrays (siehe Array Länge auf , warum dies wichtig ist ) eine dritte Option auf 0-out Array ist möglich:

 memset(array, 0, sizeof array); /* Use size of the array itself. */

Arraylänge

Arrays haben feste Längen, die im Rahmen ihrer Deklarationen bekannt sind. Trotzdem ist es möglich und manchmal bequem, die Feldlänge zu berechnen. Dies kann insbesondere den Code flexibler machen, wenn die Arraylänge automatisch von einem Initialisierer bestimmt wird:

int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

/* size of `array` in bytes */
size_t size = sizeof(array);

/* number of elements in `array` */
size_t length = sizeof(array) / sizeof(array[0]); 

In den meisten Kontexten, in denen ein Array in einem Ausdruck enthalten ist, wird es jedoch automatisch in einen Zeiger auf das erste Element konvertiert ("zerlegt"). Der Fall, in dem ein Array der Operand des Operators sizeof , ist einer von sizeof Ausnahmen. Der resultierende Zeiger ist selbst kein Array und enthält keine Informationen über die Länge des Arrays, von dem er abgeleitet wurde. Wenn diese Länge in Verbindung mit dem Zeiger benötigt wird, beispielsweise wenn der Zeiger an eine Funktion übergeben wird, muss er separat übermittelt werden.

Angenommen, wir möchten eine Funktion schreiben, um das letzte Element eines Arrays von int . Wenn wir von oben aus fortfahren, könnten wir es so nennen:

/* array will decay to a pointer, so the length must be passed separately */
int last = get_last(array, length);

Die Funktion könnte folgendermaßen implementiert werden:

int get_last(int input[], size_t length) {
    return input[length - 1];
}

Insbesondere ist zu beachten , dass , obwohl die Erklärung der input ähnelt dem eines Arrays, es in der Tat erklärt input als Zeiger (bis int ). Es ist genau gleichbedeutend mit der Deklaration der input als int *input . Das Gleiche würde auch gelten, wenn eine Dimension gegeben würde. Dies ist möglich, weil Arrays nicht immer tatsächliche Argumente für Funktionen sein können (sie zerfallen zu Zeigern, wenn sie in Funktionsaufrufausdrücken erscheinen) und sie können als Mnemonik betrachtet werden.

Es ist ein sehr häufiger Fehler, zu versuchen, die Array-Größe anhand eines Zeigers zu ermitteln, der nicht funktionieren kann. MACH DAS NICHT:

int BAD_get_last(int input[]) {
    /* INCORRECTLY COMPUTES THE LENGTH OF THE ARRAY INTO WHICH input POINTS: */
    size_t length = sizeof(input) / sizeof(input[0]));

    return input[length - 1];  /* Oops -- not the droid we are looking for */
}

Tatsächlich ist dieser bestimmte Fehler so häufig, dass einige Compiler ihn erkennen und davor warnen. clang wird beispielsweise folgende Warnung ausgegeben:

warning: sizeof on array function parameter will return size of 'int *' instead of 'int []' [-Wsizeof-array-argument]
        int length = sizeof(input) / sizeof(input[0]);
                           ^
note: declared here
int BAD_get_last(int input[])
                     ^

Einstellungswerte in Arrays

Der Zugriff auf Array-Werte erfolgt im Allgemeinen über eckige Klammern:

int val;
int array[10];

/* Setting the value of the fifth element to 5: */
array[4] = 5;

/* The above is equal to: */
*(array + 4) = 5;

/* Reading the value of the fifth element: */
val = array[4];

Als Nebeneffekt der Operanden auf den austauschbaren Operator + (-> Kommutativgesetz) ist Folgendes gleichwertig:

*(array + 4) = 5;
*(4 + array) = 5;

so gut wie die nächsten Aussagen sind gleichwertig:

array[4] = 5;
4[array] = 5; /* Weird but valid C ... */

und diese beiden auch:

val = array[4];
val = 4[array]; /* Weird but valid C ... */

C führt keine Grenzprüfungen, die Inhalte außerhalb der deklarierte Array Zugriff ist nicht definiert ( Zugriff über chunk zugewiesen Speicher ):

int val;
int array[10];

array[4] = 5;    /* ok */
val = array[4];  /* ok */
array[19] = 20;  /* undefined behavior */
val = array[15]; /* undefined behavior */

Definieren Sie Array- und Access-Array-Elemente

#include <stdio.h>
 
#define ARRLEN (10)

int main (void) 
{

   int n[ ARRLEN ]; /* n is an array of 10 integers */
   size_t i, j; /* Use size_t to address memory, that is to index arrays, as its guaranteed to 
                   be wide enough to address all of the possible available memory. 
                   Using signed integers to do so should be considered a special use case, 
                   and should be restricted to the uncommon case of being in the need of 
                   negative indexes. */
 
   /* Initialize elements of array n. */         
   for ( i = 0; i < ARRLEN ; i++ ) 
   {
      n[ i ] = i + 100; /* Set element at location i to i + 100. */
   }
   
   /* Output each array element's value. */
   for (j = 0; j < ARRLEN ; j++ ) 
   {
      printf("Element[%zu] = %d\n", j, n[j] );
   }
 
   return 0;
}

Ordnen Sie ein Array mit benutzerdefinierter Größe zu und initialisieren Sie es mit Null

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


int main (void)
{
  int * pdata;
  size_t n;

  printf ("Enter the size of the array: ");
  fflush(stdout); /* Make sure the prompt gets printed to buffered stdout. */

  if (1 != scanf("%zu", &n)) /* If zu is not supported (Windows?) use lu. */
  {
    fprintf("scanf() did not read a in proper value.\n");
    exit(EXIT_FAILURE);
  }

  pdata = calloc(n, sizeof *pdata);
  if (NULL == pdata) 
  {
    perror("calloc() failed"); /* Print error. */
    exit(EXIT_FAILURE);
  }

  free(pdata); /* Clean up. */

  return EXIT_SUCCESS;
}

Dieses Programm versucht, einen vorzeichenlosen Integer-Wert von der Standardeingabe zu scannen, ordnet einen Speicherblock für ein Array von n Elementen des Typs int indem die Funktion calloc() . Der Speicher wird von letzteren auf alle Nullen initialisiert.

Im Erfolgsfall wird der Speicher durch den Aufruf von free() .

Iteration durch ein Array effizient und Reihenreihenfolge

Arrays in C können als zusammenhängender Speicherbereich betrachtet werden. Genauer gesagt ist die letzte Dimension des Arrays der zusammenhängende Teil. Wir nennen dies die Reihenreihenfolge . Wenn Sie dies und die Tatsache verstehen, dass ein Cache-Fehler beim Zugriff auf nicht zwischengespeicherte Daten eine vollständige Cache-Zeile in den Cache lädt, um nachfolgende Cache-Fehler zu vermeiden, können Sie sehen, warum beim Zugriff auf ein Array der Dimension 10000x10000 mit array[0][0] möglicherweise array[0][1] im Cache, aber ein direkter Zugriff auf array[1][0] würde zu einem zweiten Cache-Fehler führen, da er sizeof(type)*10000 Byte von array[0][0] ist und daher sicherlich nicht in derselben Cachezeile. Deshalb ist das Iterieren ineffizient:

#define ARRLEN 10000
int array[ARRLEN][ARRLEN];

size_t i, j;
for (i = 0; i < ARRLEN; ++i)
{
    for(j = 0; j < ARRLEN; ++j)
    {
        array[j][i] = 0;
    }
}

Und so zu iterieren ist effizienter:

#define ARRLEN 10000
int array[ARRLEN][ARRLEN];

size_t i, j;
for (i = 0; i < ARRLEN; ++i)
{
    for(j = 0; j < ARRLEN; ++j)
    {
        array[i][j] = 0;
    }
}

Dies ist der gleiche Grund, warum es beim Umgang mit einem Array mit einer Dimension und mehreren Indizes (der Einfachheit halber mit den Indizes i und j zwei Dimensionen genannt wird) wichtig, das Array folgendermaßen zu durchlaufen:

#define DIM_X 10
#define DIM_Y 20

int array[DIM_X*DIM_Y];

size_t i, j;
for (i = 0; i < DIM_X; ++i)
{
    for(j = 0; j < DIM_Y; ++j)
    {
        array[i*DIM_Y+j] = 0;
    }
}

Oder mit 3 Dimensionen und Indizes i, j und k:

#define DIM_X 10
#define DIM_Y 20
#define DIM_Z 30

int array[DIM_X*DIM_Y*DIM_Z];

size_t i, j, k;
for (i = 0; i < DIM_X; ++i)
{
    for(j = 0; j < DIM_Y; ++j)
    {
        for (k = 0; k < DIM_Z; ++k)
        {
            array[i*DIM_Y*DIM_Z+j*DIM_Z+k] = 0;
        }
    }
}

Oder generischer, wenn wir ein Array mit N1 x N2 x ... x Nd Elementen, d Dimensionen und Indizes haben, die als n1, n2, ... bezeichnet werden, und der Versatz so berechnet wird

Formel

Bild / Formel entnommen aus: https://en.wikipedia.org/wiki/Row-major_order

Mehrdimensionale Arrays

Die Programmiersprache C erlaubt mehrdimensionale Arrays . Hier ist die allgemeine Form einer multidimensionalen Arraydeklaration:

type name[size1][size2]...[sizeN];

Die folgende Deklaration erstellt beispielsweise ein dreidimensionales (5 x 10 x 4) Ganzzahl-Array:

int arr[5][10][4];

Zweidimensionale Arrays

Die einfachste Form eines mehrdimensionalen Arrays ist das zweidimensionale Array. Ein zweidimensionales Array ist im Wesentlichen eine Liste von eindimensionalen Arrays. Um ein zweidimensionales ganzzahliges Array mit Dimensionen mxn zu deklarieren, können wir wie folgt schreiben:

type arrayName[m][n];

Dabei kann type ein beliebiger gültiger C-Datentyp ( int , float usw.) und arrayName ein beliebiger gültiger C-Bezeichner sein. Ein zweidimensionales Array kann als Tabelle mit m Zeilen und n Spalten dargestellt werden. Hinweis : Die Reihenfolge ist in C von Bedeutung. Das Array int a[4][3] stimmt nicht mit dem Array int a[3][4] . Die Anzahl der Zeilen kommt zuerst als eine Zeile C -Major Sprache ist.

Ein zweidimensionales Array a , das drei Zeilen und vier Spalten enthält, kann wie folgt dargestellt werden:

visuelles Layout eines 2D-Arrays als Tabelle

Somit wird jedes Element in dem Array a durch einen Elementnamen der Form a[i][j] identifiziert, wobei a der Name des Arrays ist, i die Zeile und j die Spalte darstellt. Erinnern Sie sich daran, dass Zeilen und Spalten null sind. Dies ist der mathematischen Schreibweise für die Subskription von 2-D-Matrizen sehr ähnlich.

Initialisieren von zweidimensionalen Arrays

Mehrdimensionale Arrays können durch Angabe von Klammerwerten für jede Zeile initialisiert werden. Im Folgenden wird ein Array mit 3 Zeilen definiert, wobei jede Zeile 4 Spalten hat.

int a[3][4] = {  
   {0, 1, 2, 3} ,   /*  initializers for row indexed by 0 */
   {4, 5, 6, 7} ,   /*  initializers for row indexed by 1 */
   {8, 9, 10, 11}   /*  initializers for row indexed by 2 */
};

Die geschachtelten geschweiften Klammern, die die beabsichtigte Zeile angeben, sind optional. Die folgende Initialisierung entspricht dem vorherigen Beispiel:

int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

Die Methode zum Erstellen von Arrays mit geschachtelten geschweiften Klammern ist optional, wird jedoch dringend empfohlen, da sie lesbarer und übersichtlicher ist.

Zugriff auf zweidimensionale Arrayelemente

Auf ein Element in einem zweidimensionalen Array wird mit den Indizes zugegriffen, z. B. Zeilenindex und Spaltenindex des Arrays. Zum Beispiel -

int val = a[2][3];

Die obige Anweisung nimmt das 4. Element aus der 3. Zeile des Arrays. Lassen Sie uns das folgende Programm überprüfen, in dem wir eine geschachtelte Schleife verwendet haben, um ein zweidimensionales Array zu behandeln:

#include <stdio.h>
 
int main () {

   /* an array with 5 rows and 2 columns*/
   int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};
   int i, j;
 
   /* output each array element's value */
   for ( i = 0; i < 5; i++ ) {

      for ( j = 0; j < 2; j++ ) {
         printf("a[%d][%d] = %d\n", i,j, a[i][j] );
      }
   }
   
   return 0;
}

Wenn der obige Code kompiliert und ausgeführt wird, führt er zu folgendem Ergebnis:

a[0][0]: 0
a[0][1]: 0
a[1][0]: 1
a[1][1]: 2
a[2][0]: 2
a[2][1]: 4
a[3][0]: 3
a[3][1]: 6
a[4][0]: 4
a[4][1]: 8

Dreidimensionales Array:

Ein 3D-Array ist im Wesentlichen ein Array von Arrays: Es handelt sich um ein Array oder eine Sammlung von 2D-Arrays, und ein 2D-Array ist ein Array von 1D-Arrays.

visuelles Layout eines 2D-Arrays als Tabellensammlung

3D-Array-Speicherzuordnung:

3D-Array ist zusammenhängend im Speicher angeordnet

Initialisieren eines 3D-Arrays:

double cprogram[3][2][4]={ 
{{-0.1, 0.22, 0.3, 4.3}, {2.3, 4.7, -0.9, 2}},
 {{0.9, 3.6, 4.5, 4}, {1.2, 2.4, 0.22, -1}},
 {{8.2, 3.12, 34.2, 0.1}, {2.1, 3.2, 4.3, -2.0}} 
};

Wir können Arrays mit einer beliebigen Anzahl von Dimensionen haben, obwohl es wahrscheinlich ist, dass die meisten der erstellten Arrays eine oder zwei Dimensionen haben.

Durchlaufen eines Arrays mit Zeigern

#include <stdio.h>
#define SIZE (10)
int main()
{
    size_t i = 0;
    int *p = NULL;
    int a[SIZE];
    
    /* Setting up the values to be i*i */
    for(i = 0; i < SIZE; ++i) 
    {
        a[i] = i * i;
    }
    
    /* Reading the values using pointers */
    for(p = a; p < a + SIZE; ++p) 
    {
        printf("%d\n", *p);
    }

    return 0;
}

Bei der Initialisierung von p in der ersten for Schleifenbedingung zerfällt das Array a zu einem Zeiger auf sein erstes Element, wie es an fast allen Stellen der Fall wäre, an denen eine solche Arrayvariable verwendet wird.

Dann führt ++p eine Zeigerarithmetik für den Zeiger p und geht die Elemente des Arrays nacheinander durch und referenziert sie, indem sie mit *p dereferenziert werden.

Übergeben von mehrdimensionalen Arrays an eine Funktion

Mehrdimensionale Arrays folgen den gleichen Regeln wie eindimensionale Arrays, wenn sie an eine Funktion übergeben werden. Die Kombination von Decay-to-Pointer, Operator-Vorrang und die zwei verschiedenen Arten, ein mehrdimensionales Array (Array von Arrays vs. Array von Zeigern) zu deklarieren, kann die Deklaration solcher Funktionen jedoch nicht intuitiv machen. Das folgende Beispiel zeigt, wie Sie mehrdimensionale Arrays richtig übergeben können.

#include <assert.h>
#include <stdlib.h>

/* When passing a multidimensional array (i.e. an array of arrays) to a
   function, it decays into a pointer to the first element as usual.  But only
   the top level decays, so what is passed is a pointer to an array of some fixed
   size (4 in this case). */
void f(int x[][4]) {
    assert(sizeof(*x) == sizeof(int) * 4);
}

/* This prototype is equivalent to f(int x[][4]).
   The parentheses around *x are required because [index] has a higher
   precedence than *expr, thus int *x[4] would normally be equivalent to int
   *(x[4]), i.e. an array of 4 pointers to int.  But if it's declared as a
   function parameter, it decays into a pointer and becomes int **x, 
   which is not compatable with x[2][4]. */
void g(int (*x)[4]) {
    assert(sizeof(*x) == sizeof(int) * 4);
}

/* An array of pointers may be passed to this, since it'll decay into a pointer
   to pointer, but an array of arrays may not. */
void h(int **x) {
    assert(sizeof(*x) == sizeof(int*));
}

int main(void) {
    int foo[2][4];
    f(foo);
    g(foo);

    /* Here we're dynamically creating an array of pointers.  Note that the 
       size of each dimension is not part of the datatype, and so the type 
       system just treats it as a pointer to pointer, not a pointer to array
       or array of arrays. */
    int **bar = malloc(sizeof(*bar) * 2);
    assert(bar);
    for (size_t i = 0; i < 2; i++) {
        bar[i] = malloc(sizeof(*bar[i]) * 4);
        assert(bar[i]);
    }

    h(bar);
    
    for (size_t i = 0; i < 2; i++) {
        free(bar[i]);
    }
    free(bar);
}

Siehe auch

Übergabe von Arrays an Funktionen



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow