Die übergabe eines mehrdimensionalen variable Länge array an eine Funktion
Es gibt Unmengen von ähnlichen Fragen, aber noch konnte ich nicht finden, jede Antwort, die relevant für die Funktion von variabler Länge arrays in C99/C11.
Wie pass mehrdimensionale variable Länge array, um eine Funktion in C99/C11?
Beispiel:
void foo(int n, int arr[][]) //<-- error here, how to fix?
{
}
void bar(int n)
{
int arr[n][n];
foo(n, arr);
}
Compiler (g++-4.7 -std=gnu++11
) sagt:
error: declaration of ‘arr’ as multidimensional array must have bounds for all dimensions except the first
Wenn ich es ändern zu int *arr[]
, der compiler beschwert sich trotzdem:
error: cannot convert ‘int (*)[(((sizetype)(((ssizetype)n) + -1)) + 1)]’ to ‘int**’ for argument ‘2’ to ‘void foo(int, int**)’
Nächste Frage, wie er als Wert übergeben werden und wie es passieren Referenz? Anscheinend, in der Regel wollen Sie nicht das gesamte array kopiert werden, wenn Sie übergeben es an eine Funktion.
Mit konstanter Länge von arrays es ist ganz einfach, da, wie die "konstant" bedeutet, Sie sollten wissen, die Länge, wenn Sie die Funktion deklarieren:
void foo2(int n, int arr[][10]) //<-- ok
{
}
void bar2()
{
int arr[10][10];
foo2(10, arr);
}
Ich weiß, arrays an Funktionen übergeben wie dies ist nicht best-practice, und ich don ' T wie es überhaupt. Es ist wohl besser, mit flat-Zeiger oder Objekte (wie std:vector) oder irgendwie sonst. Aber dennoch, ich bin ein bisschen gespannt, was ist die Antwort hier von einem theoretischen Standpunkt aus.
std::vector<std::vector<int>>
und vermeiden Sie alle diese Probleme?VLAs sind nicht in C++11.
Die Antwort aus theoretischer Sicht ist: "Du kannst das nicht". Bei der übergabe eines Arrays als parameter, bekommt man nur ein "free" - dimension. Die anderen müssen angegeben werden als Konstante Ausdrücke (d.h., die Werte bekannt zu entsc Zeit).
ein Vektor von Vektoren gibt Ihnen viel zu viel Freiheit zu definieren, Ihre dimension (
arr[0]
hätte Größe 3
, arr[1]
Größe 5
, und so weiter). Ich denke, zu Steigern.MultiArray ist die richtige Wahl.Ich bin damit einverstanden. Ich würde es einpacken in eine Art von matrix-Klasse.
InformationsquelleAutor alveko | 2013-01-27
Du musst angemeldet sein, um einen Kommentar abzugeben.
Arrays an Funktionen übergeben ist ein bisschen komisch in C und C++. Es gibt keine rvalues von array-Typen, Sie sind also eigentlich wird ein Zeiger übergeben.
Adresse ein 2D-array (ein echtes, kein array von arrays), die Sie brauchen, um pass 2 Datenblöcke:
Und diese sind zwei separate Werte, sei es C oder C++ oder mit VLA oder ohne oder ähnliches.
Einige Möglichkeiten, dass zu schreiben:
Einfachste, die funktioniert überall, benötigt aber etwas mehr manuelle Arbeit
VLA, standard C99
VLA w/reversed Argumente, vorwärts parameter Erklärung (GNU-C Erweiterung)
C++ w/VLA (GNU C++ - Erweiterung, furchtbar hässlich)
Big Bemerkung:
[X][y] - notation mit einem 2D-array funktioniert, weil das array enthält die Breite. Kein VLA = array-Typen behoben werden muss zur compile-Zeit.
Daher: Wenn Sie nicht verwenden können, VLA, dann...
Wenn Sie verwenden können, VLA (C99 oder die GNU C++ Erweiterungen), dann...
C++
boost::multi_array
ist eine gute Wahl.Ein workaround
Für 2D-arrays sind, können Sie zwei getrennte Zuordnungen:
T
(A)T
(B)Dann setzen Sie den Zeiger (A) zu zeigen in den jeweiligen Zeilen von (B).
Mit diesem setup können Sie einfach pass (A) um sich als eine einfache
T**
und es verhält sich auch mit[x][y]
Indizierung.Diese Lösung ist schön für 2D, aber braucht mehr und mehr boilerplate für höhere Dimensionen. Es ist auch langsamer als der VLA-Lösung, weil der zusätzliche Schicht der Dereferenzierung.
Es kann auch eine ähnliche Lösung mit einer separaten Zuweisung für jeden
B
's row. In C sieht es wie ein malloc-in-a-loop, und ist Analog der C++'s Vektor von Vektoren. Allerdings dauert dieser Weg den Vorteil, dass das gesamte array in einen block.void foo(arr, width) int width; int arr[][width] {}
. Umgekehrt args w/ K / &R-syntax. Ich habe es nicht gesehen in freier Wildbahn allerdings noch nicht.in C++11 (mit Clang zumindest), Sie können von prettify die C++ - Beispiel zu
auto arr = reinterpret_cast<int (&)[][width]>(ptr);
Oder, wenn Sie möchten, eine explizite Art, finden Sie möglicherweise
using arrtype = int[][width];
schöner alstypedef int arrtype[][width];
Wie rufe ich jede Funktion? C-variable Länge-array ist nicht
int*
geben.Das ist sehr lehrreich
InformationsquelleAutor Kos
Gibt es keine klaren Weg, dies zu tun, aber Sie können einen workaround zur Behandlung einer 2-dimensionalen array als ein ein-dimensionales array und dann reconvert es sich um ein zwei-dimensionales array in der Funktion.
InformationsquelleAutor Pankaj Rai