Zunächst einige standard Sprache:
6.3.2.1 Lvalues, Arrays und Funktion Bezeich
...
3 Außer wenn es der Operand des sizeof Operator oder unary & operator, oder ist ein String-Literal, das zum Initialisieren eines Arrays verwendet wird, wird ein Ausdruck vom Typ "array of type" in einen Ausdruck mit dem Typ "pointer to type" konvertiert, der auf das ursprüngliche Element des Array-Objekts zeigt ein Wert. Wenn das Array-Objekt über eine Regis- terspeicherklasse verfügt, ist das Verhalten nicht definiert.
die Deklaration
Gegeben
int myarray[3][3];
der Typ von myarray
"3-Element-Array von 3-Element-Array von int
" ist.Geht durch die Regel oben, wenn man
MyFunction(myarray, 3, 3);
der Ausdruckmyarray
seinen Typen zu schreiben implizit konvertiert hat ("decay") von "3-Element-Array von 3-Element-Array von int
" auf „Zeiger auf 3 -Elementarray von int
"oder int (*)[3]
.
So würde Ihre Funktionsprototyp
int MyFunction(int (*array)[3], int row, int col)
Beachten Sie, dass int **array
ist nicht die gleiche wie int (*array)[3]
sein müssen; Die Zeigerarithmetik wird anders sein, sodass Ihre Indizes nicht auf die richtigen Stellen zeigen. Denken Sie daran, dass Array-Indexierung in Bezug auf Zeigerarithmetik definiert ist: a[i]
== *(a+i)
, a[i][j] == *(*(a + i) + j)
. a+i
ergibt einen anderen Wert abhängig davon, ob a
ein int **
oder ein int (*)[N]
ist.
In diesem speziellen Beispiel wird davon ausgegangen, dass Sie immer ein Nx3-Element-Array von int
; nicht besonders flexibel, wenn Sie mit einem NxM-großen Array arbeiten möchten. Eine Möglichkeit, dies zu umgehen wäre ausdrücklich passieren die Adresse des ersten Elements in der Anordnung, so dass Sie vorbei nur einen einfachen Zeiger, und dann berechnet die richtigen manuell versetzt:
void MyFunction(int *arr, int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf("%d", a[i*col+j]);
}
int main(void)
{
int myarray[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
...
MyFunction(&myarray[0][0], 3, 3);
Da wir übergeben Sie einen einfachen Zeiger auf int
, können wir nicht einen doppelten Index in MyFunc
verwenden; Das Ergebnis von arr[i]
ist ein Integer, kein Zeiger, also müssen wir den vollständigen Offset in das Array in der Ein-Index-Operation berechnen. Beachten Sie, dass dieser Trick nur für wirklich mehrdimensionale Arrays funktioniert.
nun ein **
kann zeigen Werte, die in einer 2-D-Struktur organisiert sind, aber eine, die eine andere Art und Weise gebaut wurde. Zum Beispiel:
void AnotherFunc(int **arr, int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf("%d", arr[i][j]);
}
int main(void)
{
int d0[3] = {1, 2, 3};
int d1[3] = {4, 5, 6};
int d2[3] = {7, 8, 9};
int *a[3] = {d0, d1, d2};
AnotherFunc(a, 3, 3);
...
}
Going durch die Regel oben, wenn die Ausdrücke d0
, d1
und d2
in dem Initialisierer für a
erscheinen, sind alle Arten von „3-Element-Array von int
“ auf „Zeiger auf umgewandelt int
". Wenn der Ausdruck a
in dem Aufruf von AnotherFunc
angezeigt wird, wird sein Typ in ähnlicher Weise von "3-Elementarray des Zeigers zu int
" in "Zeiger auf Zeiger auf int
" konvertiert.
Beachten Sie, dass wir in AnotherFunc
beide Dimensionen indizieren, anstatt den Offset wie in MyFunc
zu berechnen. Das liegt daran, a
ist ein Array von Zeiger Werte. Der Ausdruck arr[i]
bekommt uns die i'th Zeiger Wert Offset von der Position arr
; Wir finden dann den j-ten ganzzahligen Wert-Offset von diesem Zeigerwert.
Die folgende Tabelle helfen könnte - es zeigt die Typen verschiedener Array Ausdrücke und was sie zerfallen zu auf der Grundlage ihrer Erklärungen (T (*)[N]
ist ein Zeigertyp, kein Array-Typ, so dass es nicht zerfallen ist):
Declaration Expression Type Implicitly Converted (Decays) to
----------- ---------- ---- --------------------------------
T a[N] a T [N] T *
&a T (*)[N]
*a T
a[i] T
T a[M][N] a T [M][N] T (*)[N]
&a T (*)[M][N]
*a T [N] T *
a[i] T [N] T *
&a[i] T (*)[N]
*a[i] T
a[i][j] T
T a[L][M][N] a T [L][M][N] T (*)[M][N]
&a T (*)[L][M][N]
*a T [M][N] T (*)[N]
a[i] T [M][N] T (*)[N]
&a[i] T (*)[M][N]
*a[i] T [N] T *
a[i][j] T [N] T *
&a[i][j] T (*)[N]
*a[i][j] T
a[i][j][k] T
Das Muster für höherdimensionale Arrays sollte klar sein.
Ich fand dies sehr hilfreich beim Starten von C-Programmierung: http://cslibrary.stanford.edu/102/PointersAndMemory.pdf – helpermethod
werfen Sie einen Blick auf den Array vs Zeiger Abschnitt der C-FAQ (http: // c- faq.com/aryptr/index.html) – pmg