Wie übergebe ich ein 2D-Array (Matrix) in einer Funktion in C?

72

Ich muss dies tun, um auch Operationen in der Matrix beizubehalten. Bedeutet das, dass es als Referenz übergeben werden muss?

Wird das ausreichen?

void operate_on_matrix(char matrix[][20]);

Shweta
quelle

Antworten:

124

C hat nicht wirklich mehrdimensionale Arrays, aber es gibt verschiedene Möglichkeiten, sie zu simulieren. Die Art und Weise, wie solche Arrays an eine Funktion übergeben werden, hängt von der Art und Weise ab, wie die mehreren Dimensionen simuliert werden:

1) Verwenden Sie ein Array von Arrays. Dies kann nur verwendet werden, wenn Ihre Array-Grenzen zur Kompilierungszeit vollständig festgelegt sind oder wenn Ihr Compiler VLAs unterstützt :

2) Verwenden Sie ein (dynamisch zugewiesenes) Array von Zeigern auf (dynamisch zugewiesene) Arrays. Dies wird meistens verwendet, wenn die Array-Grenzen erst zur Laufzeit bekannt sind.

3) Verwenden Sie ein eindimensionales Array und korrigieren Sie die Indizes. Dies kann sowohl mit statisch zugewiesenen (feste Größe) als auch mit dynamisch zugewiesenen Arrays verwendet werden:

4) Verwenden Sie eine dynamisch zugewiesene VLA. Ein Vorteil gegenüber Option 2 besteht darin, dass nur eine Speicherzuordnung vorhanden ist. Zum anderen wird weniger Speicher benötigt, da das Array von Zeigern nicht benötigt wird.

(Siehe srand()- warum nur einmal anrufen? )

Bart van Ingen Schenau
quelle
Auf die oben erwähnte erste Weise wird der Code nicht kompiliert. "Zeilen" und "Spalten" in den Zeilen 17 und 35 müssen in "Zeilen" bzw. "Spalten" geändert werden.
KZcoding
5
void func_vla(int array[rows][cols], int rows, int cols)sollte seinvoid func_vla(int rows, int cols, int array[rows][cols])
David Ranieri
@KZcoding: Die in den Zeilen 17 und 35 verwendete VLA-Notation ist korrekt, wenn der Compiler C99 unterstützt oder wenn er C11 unterstützt und nicht definiert __STDC_NO_VLA__. Wenn der Compiler keine VLAs unterstützt, wird er natürlich nicht kompiliert.
Jonathan Leffler
malloc gibt einen ungültigen Zeiger zurück. Sind Sie sicher, dass Sie ihn nicht nach Bedarf in int * oder int ** umwandeln müssen? Lösung 2
Liger
Casting ist eher eine C ++ - Konvention, verstanden! Danke @BartvanIngenSchenau
Liger
12

Ich weiß nicht, was Sie unter "Daten gehen nicht verloren" verstehen. So übergeben Sie ein normales 2D-Array an eine Funktion:

casablanca
quelle
21
Zufälliges Faktoid: Der Grund, warum N erforderlich ist, liegt darin, dass der Computer wissen muss, wie weit der Zeiger für jede "Zeile" inkrementiert werden muss. Wirklich sind alle Dimensionen außer der ersten notwendig. C speichert Arrays als Speicherblöcke ohne Trennzeichen.
Christian Mann
Daten gehen nicht verloren, ohne malloc zu verwenden. Danke für die Hilfe.
Shweta
1
@ Christian Mann: Das ist ein gutes Faktoid. Ich habe heute zufällig eine ausführliche Erklärung dazu geschrieben :-) stackoverflow.com/questions/3906777/…
Arun
Es scheint, dass heute jeder Probleme mit mehrdimensionalen Arrays hat. :) Ich schrieb eine ähnliche Erklärung auch in einer anderen Frage: stackoverflow.com/questions/3911244/…
casablanca
2
@ChristianMann Der Grund, warum die Array-Syntax überhaupt funktioniert, ist vielmehr, dass der Compiler die Array-Deklaration im Parameter in diesem Fall an einen Zeiger auf das erste Element anpasst int (*)[N]. Und deshalb müssen auch alle Dimensionen außer der äußersten angegeben werden - das Array zerfällt nur einmal. Dies hat absolut nichts mit dem zu tun, was "der Computer wissen muss" - Unsinn. Vergleichen Sie es mit dem 1D-Fall void func (int [n]):, der angepasst wird void func (int*)und alle Größeninformationen verloren gehen - "der Computer" erfährt nichts und der Compiler könnte es nicht weniger interessieren.
Lundin
9

Der einfachste Weg, ein 2D-Array mit variabler Länge zu übergeben

Die sauberste Technik für C und C ++ ist: Übergeben Sie ein 2D-Array wie ein 1D-Array und verwenden Sie es dann als 2D innerhalb der Funktion.

Unabhängig von der Anzahl der Dimensionen eines Arrays verwaltet C / C ++ intern immer ein 1D-Array. Und so können wir jedes mehrdimensionale Array wie dieses übergeben.

Minhas Kamal
quelle
Nur eine kleine Frage: Wenn wir die Funktion wie aufrufen func(2, 3, matrix), sollten wir dann haben void func(int row, int col, int** matrix)?
Kartik Chhajed
@KartikChhajed Ihr Code erfordert eine implizite Konvertierung von int*[3]nach int**, was für die meisten C / C ++ - Compiler möglicherweise nicht zulässig ist.
Minhas Kamal
@jwpol leider ist es keine gute Idee: stackoverflow.com/q/25303647/1606345
David Ranieri
@ David Ranieri Wenn Sie die Dimension des Arrays kennen, kann ich keinen Grund erkennen, warum Sie ein bestimmtes Element nicht dereferenzieren sollten. Zum Beispiel int matrix[2][2]belegt 4 "Zellen" des Speichers, so dass von *(p)bis *(p+3)(wobei p eine Adresse des ersten Elements ist) innerhalb der Dimension des zugewiesenen Speichers liegen. Gleiches gilt für diese Antwort. In dem von Ihnen geposteten Thread geht es darum, ein Element nach dem letzten im Array zu dereferenzieren, was hier nicht der Fall ist. Die Antwort von @Minhas Kamal ist absolut sicher, vorausgesetzt, Sie überschreiten legitime Grenzen in rawund col.
JWPol
1

2D-Array:

3D-Array:

4D-Array:

und nD Array:

Shinxg
quelle