Korrekte Methode zum Übergeben eines zweidimensionalen Arrays an eine Funktion

Lesezeit: 7 Minuten

Benutzeravatar von lakshmen
Lakshmen

Ich habe ein zweidimensionales Array und übergebe es an eine Funktion, um bestimmte Operationen auszuführen. Ich würde gerne wissen, wie man es richtig macht…

#define numRows 3
#define numCols 7
#define TotalNum (numRows*numCols)
int arr[numRows][numCols] = {{0,1,2,3,4,5,6}, {7,8,9,10,11,12,13},{14,15,16,17,18,19,20}};

void display(int **p)
{
    printf("\n");
    for (int i = 0; i< numRows;i++)
    {
        for ( int j = 0;j< numCols;j++)
        {
            printf("%i\t",p[i][j]);
        }
        printf("\n");
    }
}

int main() {
    display(arr);
}

Ich bekomme eine Fehlermeldung:

'display': cannot convert parameter1 from 'int' to 'int*'

Ist dies der richtige Weg, ein zweidimensionales Array an eine Funktion zu übergeben? Wenn nicht, was ist der richtige Weg?

  • mögliches Duplikat von C – Übergabe eines 2D-Arrays als Funktionsargument?

    – Bo Persson

    25. Februar 2012 um 21:03 Uhr

  • Kleiner Tipp: Verwenden Sie CAPS für Makros, dies ist die gängige Praxis und kann Ihren Code für Außenstehende viel klarer machen

    – Shmil die Katze

    14. März 2014 um 11:11 Uhr

  • Obwohl die Absicht der Frage hier darin besteht, zu verstehen, wie 2D-Arrays an Funktionen übergeben werden, sollte arr, um dem obigen Beispiel Korrektheit hinzuzufügen, lokal zu main sein.

    – Benutzer376507

    22. November 2015 um 20:49 Uhr

Sie sollten Ihre Funktion wie folgt deklarieren:

void display(int p[][numCols])

Dies C-Häufig gestellte Fragen erklärt ausführlich warum. Der Kern davon ist, dass Arrays in Zeiger zerfallen einmal, es passiert nicht rekursiv. Ein Array von Arrays zerfällt in einen Zeiger auf ein Array, nicht in einen Zeiger auf einen Zeiger.

  • Ich habe eine Frage. Diese Funktion soll es anzeigen, aber wenn es verwendet wird, um die Werte in der arr zu ändern?

    – Lakshmen

    25. Februar 2012 um 19:22 Uhr

  • @cnicutar, also können wir int nicht konvertieren*[20] zu int**. Ist das der Grund?

    – Gibbs

    31. Oktober 2014 um 6:37 Uhr

Benutzeravatar von asaelr
asaelr

Wenn Sie (wie in Ihrem Fall) die Dimensionen des Arrays zur Kompilierzeit kennen, können Sie einfach schreibenvoid display(int p[][numCols]).

Einige Erklärungen: Sie wissen wahrscheinlich, dass Sie beim Übergeben eines Arrays an eine Funktion tatsächlich einen Zeiger auf das erste Element übergeben. In der C-Sprache ist ein 2D-Array nur ein Array von Arrays. Aus diesem Grund sollten Sie der Funktion einen Zeiger auf das erste Unterarray im 2D-Array übergeben. Also, der natürliche Weg, ist zu sagen int (*p)[numCols] (das bedeutet p ist ein Zeiger auf ein Array von numCols int). In der Funktionsdeklaration haben Sie die “Verknüpfung” p[]das bedeutet genau dasselbe wie (*p) (Aber teilt dem Leser mit, dass Sie einen Zeiger auf den Anfang eines Arrays übergeben und nicht nur auf eine Eins-Variable)

Benutzeravatar von lord.garbage
Herr.Müll

Dazu gibt es mehrere, teilweise gleichwertige Möglichkeiten. Durch die Deklaration eines Arrays (vgl. method_c()), durch Verwendung eines Zeigers (vgl. method_b()) oder durch Verwendung eines Zeigers auf ein Array eines Arrays (vgl. method_a()). method_b()mit einem einzelnen Zeiger, ist etwas schwieriger, da es nicht einfach ist, die standardmäßige Array-Indizierung zu verwenden, und daher verwenden wir Zeigerarithmetik. method_a() und method_c() sind im Grunde äquivalent, da Arrays während der Kompilierung nicht rekursiv zu Zeigern zerfallen. Hier ist ein kleines Programm, das alle drei Methoden veranschaulicht. Wir initialisieren zuerst a 2x4-Array arr in einer einfachen for-Schleife und drucke es aus. Es wird so aussehen:

arr:
0 1 2 3
0 1 2 3

Danach rufen wir alle drei Methoden auf. method_a() fügt 1 hinzu, method_b() addiert 2 und method_c() addiert 3 zu allen Elementen. Nach jedem Aufruf drucken wir das Array aus arr wieder. Wenn eine Funktion korrekt funktioniert hat, können Sie dies leicht in der Ausgabe sehen. Die Größe ist beliebig und kann über die beiden Makros reguliert werden ROW und COL. Eine letzte Anmerkung, method_c() stützt sich auf ein Array mit variabler Länge, das seitdem vorhanden ist C99.

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

#define ROW 2
#define COL 4

void method_a(int m, int n, int (*ptr_arr)[n]);
void method_b(int m, int n, int *ptr_arr);
void method_c(int m, int n, int arr[][n]);

int main(int argc, char *argv[]) {

    int arr[ROW][COL];

    int i;
    int j;
    for(i = 0; i < ROW; i++) {
        for(j = 0; j < COL; j++) {
            arr[i][j] = j;
        }
    }

    printf("Original array:\n");
    for (i = 0; i < ROW; i++) {
        for(j = 0; j < COL; j++) {
            printf("%d\t", arr[i][j]);
        }
        printf("\n");
    }

    printf("\n\n");

    method_a(ROW, COL, arr);

    printf("method_a() array:\n");
    for (i = 0; i < ROW; i++) {
        for(j = 0; j < COL; j++) {
            printf("%d\t", arr[i][j]);
        }
        printf("\n");
    }

    printf("\n\n");

    printf("method_b() array:\n");
    method_b(ROW, COL, (int *)arr);

    for (i = 0; i < ROW; i++) {
        for(j = 0; j < COL; j++) {
            printf("%d\t", arr[i][j]);
        }
        printf("\n");
    }

    printf("\n\n");

    method_c(ROW, COL, arr);

    printf("method_c() array:\n");
    for (i = 0; i < ROW; i++) {
        for(j = 0; j < COL; j++) {
            printf("%d\t", arr[i][j]);
        }
        printf("\n");
    }

    printf("\n\n");

    return EXIT_SUCCESS;
}

void method_a(int m, int n, int (*ptr_arr)[n])
{
    int i, j;
    for (i = 0; i < m; i++)
    {
        for (j = 0; j < n; j++)
        {
            ptr_arr[i][j] = j + 1;
        }
    }
}

void method_b(int m, int n, int *ptr_arr)
{
    int i, j;
    for (i = 0; i < m; i++)
    {
        for (j = 0; j < n; j++)
        {
            /* We need to use pointer arithmetic when indexing. */
            *((ptr_arr + i * n) + j) = j + 2;
        }
    }
    /* The whole function could have also been defined a bit different by taking
     * the i index out of the pointer arithmetic. n alone will then provide our
     * correct offset to the right. This may be a bit easier to understand. Our
     * for-loop would then look like this:
     * for (i = 0; i < m; i++)
     * {
     *     for (j = 0; j < n; j++)
     *     {
     *         *((ptr_arr + n) + j) = j + 2;
     *     }
     *     ptr_arr++;
     * }*/
}

void method_c(int m, int n, int arr[][n])
{
    int i, j;
    for (i = 0; i < m; i++)
    {
        for (j = 0; j < n; j++)
        {
            arr[i][j] = j + 3;
        }
    }
}

  • Warum müssen wir (int *)arr ausführen, während wir unser Array an method_b() übergeben?

    – Shane

    11. Juni 2016 um 9:06 Uhr

  • @lord.garbage +1 für den Hinweis auf das C99-Problem für method_c().

    – Guy Avraham

    7. Oktober 2017 um 18:02 Uhr

Benutzeravatar von Varun Chhangani
Varun Chhangani

Du machst es falsch. Sie können ein 2-D-Array mit Hilfe eines Zeigers an ein Array übergeben oder einfach ein Array oder einen einzelnen Zeiger übergeben.

#define numRows 3
#define numCols 7
void display(int (*p)[numcols],int numRows,int numCols)//First method//
void display(int *p,int numRows,int numCols) //Second Method//
void display(int numRows,int numCols,int p[][numCols])  //Third Method
{
    printf("\n");
    for (int i = 0; i < numRows;i++)
    {
        for ( int j = 0; j < numCols;j++)
        {
            printf("%i\t",p[i][j]);
        }
        printf("\n");
    }
}

int main() {
    display(arr,numRows,numCols);
}

Erklären Sie es einfach

void display(int (*p)[numCols][numRows]);

Auf diese Weise Ihre p Zeiger übermittelt alle notwendigen Informationen und Sie können ohne Wiederholung alle Dimensionen daraus extrahieren numCols und numRows über und über.

void display(int (*p)[numCols][numRows])
{
   size_t i, j;

   printf("sizeof array=%zu\n", sizeof *p);
   printf("sizeof array[]=%zu\n", sizeof **p);
   printf("sizeof array[][]=%zu\n", sizeof ***p);

   size_t dim_y = sizeof *p / sizeof **p;
   printf("dim_y = %zu\n", dim_y);

   size_t dim_x = sizeof **p / sizeof ***p;
   printf("dim_x = %zu\n", dim_x);

   for(i=0; i<dim_y; i++) {
      puts("");
      for(j=0; j<dim_x; j++)
         printf(" %6d", (*p)[i][j]);
   }
}

Dies ist besonders interessant, wenn Sie Typedefs verwenden (was ich übrigens nicht mag)

 typedef int matrix[5][6];

In diesem Fall sind die Abmessungen in der Signatur der Funktion nicht sichtbar, aber die Funktion hat immer noch die richtigen Werte für die Abmessungen.

Sie können die Signatur der Anzeigemethode wie folgt ändern:

void display(int (*p)[numCols])

Hier, p ist ein Zeiger auf die Zeile eines 2D-Arrays. Der Zeiger muss nur die Anzahl der Spalten im Array kennen.

Eigentlich muss der Zeiger die Größe jeder Zeile kennen. Dies ist sehr wichtig für die Zeigerarithmetik. Wenn Sie also den Zeiger erhöhen, muss der Zeiger auf die nächste Zeile zeigen.

Beachten Sie hier, p ist kein normaler ganzzahliger Zeiger. Es ist ein ganzzahliger Zeiger auf die Speichergröße gleich integer_size x columns.

Hauptsache du musst nichts ändern. display(arr) ist einfach gut.

1411510cookie-checkKorrekte Methode zum Übergeben eines zweidimensionalen Arrays an eine Funktion

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

Privacy policy