2016-05-11 18 views
1

Ich habe ein Problem mit den mehrdimensionalen Arrays. Vielleicht ist die Lösung viel einfacher.Mehrdimensionales Array und Adressierung

int arr[2][2]; //multidimensional array 

Meine einfache Frage ist: Warum der

arr [0] [2] und arr [1] [0] oder arr [1] [2] und arr [2] [0 ]

sind auf die gleiche Adresse in meinem Fall? Ich habe dieses Problem in Linux und Windows-Umgebung überprüft. Und das Problem ist das gleiche. Ich habe Tutorials und andere Quellen überprüft, aber keine Antwort.

+1

Wie überprüfen Sie, wie ihre Adresse ist? – mszymborski

+0

Sind Sie sicher, dass Sie nicht jedes Mal die Adresse des Basiszeigers erhalten? Das wäre meine starke Vermutung. Poste deinen Code, um die Adressen zu überprüfen. –

+2

Die Auswertung von 'arr [0] [2]' erzeugt einen Out-of-Bounds-Zugriff mit undefiniertem Verhalten. (Aber nur die Adresse zu nehmen ist in Ordnung ('& arr [0] [2]'), weil das nicht ausgewertet wird.) –

Antwort

1

Der Zeiger &arr[0][2] ist der Zeiger nach dem Ende des Arrays arr[0]. Dies ist die gleiche Adresse wie die des ersten Elements des nächsten Arrays arr[1], das ist, da Arrays zusammenhängend im Speicher angeordnet sind.

arr[2][0] ist etwas tricker: arr[2] kein gültiger Zugriff, aber &arr[2] ist die Ein-past-the-Endzeiger des Arrays arr. Aber da dieser Zeiger nicht dereferenziert werden kann, macht es keinen Sinn über arr[2][0] zu sprechen. arr hat kein drittes Element.

-2

Die Array-Indizierung in C ähnelt dem Hinzufügen des Werts des Index zur Adresse des ersten Elements.

In dem von Ihnen beschriebenen mehrdimensionalen Array haben Sie zwei Elemente für jede Dimension: 0 und 1. Wenn Sie eine größere Zahl eingeben, verweisen Sie auf ein Element außerhalb dieser Dimension. Technisch gesehen ist dies ein Array außerhalb des zulässigen Bereichs.

Die Adressen brechen wie folgt unten:

  • arr[0][0] - &arr[0] + 0
  • arr[0][1]-&arr[0] + 1
  • arr[1][0]-&arr[0] + 2
  • arr[1][0] - &arr[0] + 3

Wenn Sie arr [0] [2] schreiben, verweisen Sie auf die Adresse & arr [0] + 2, was mit arr [1] [0] übereinstimmt. Es ist alles nur Zeiger Mathematik, so dass Sie es ziemlich leicht erarbeiten können, sobald Sie wissen, wie es funktioniert.

0

C speichert multidimensionale Arrays im so genannten row-major order. In dieser Konfiguration werden alle Daten für eine einzelne Zeile in aufeinanderfolgenden Speicher gespeichert:

arr[2][2] -> r0c0, r0c1, r1c0, r1c2 

Die alternative column-Hauptordnung wäre, die nacheinander die Spalten platziert.

Da Sie die Länge der Zeile (Anzahl der Spalten) als 2 angegeben haben, wird beim Zugriff auf Spalte 2 (die dritte Spalte) eine Adresse berechnet, die zur nächsten Zeile "umgebrochen" wird.

Die Mathematik wie folgt aussieht:

&(arr[row][col]) 

= arr # base address 
+ row * ncols * sizeof(element) 
+ col * sizeof(element) 

= arr + sizeof(element) * (row * ncols + col) 

In Ihrem Fall arr[0][2]arr + (0*2 + 2) * sizeof(int) ist, während arr[1][0]arr + (1*2 + 0)*sizeof(int) ist.

Sie können ähnliche Berechnungen für die anderen Varianten durchführen.

-2

Sie in Ihrer zweidimensionalen Matrix als lang eindimensionales Array aussehen:

[00][01][10][11] 

Mit dem arithmetischen Zeiger, eine andere Darstellung dieses langen eindimensionalen Array ist:

[00][01][02][03] 

So sucht in Zelle [10] ist genau das gleiche wie in eine Zelle [20] in Zeiger-arithmetischer Sicht zu sehen.

-1

Array Indizierung ist identisch mit Zeigerarithmetik (eigentlich zuerst das Array Namen („Zerfälle“) auf einen Zeiger auf das erste Element vor dem [] -Operator angewendet wird, umgewandelt wird):

arr[r][c] <=> *(arr + r * INNER_LENGTH + c) 

Ihr Array hat zwei Einträge pro Dimension. In C beginnen Indizes von 0, so dass für jede Dimension gültige Indizes 0 und 1 sind (d. H. total_entries - 1). Das macht drei Ihrer Ausdrücke in erster Linie suspective:

arr[0][2] // [outer dimension/index][inner dimension/index] 
arr[1][2] 
arr[2][0] 

wir diese Fälle haben:

  • Beide Indizes gelten: kein Problem.
  • nur die Adresse entnommen wird, wird das Element nicht zugegriffen und
    • der äußeree Index gültig ist und die innere (siehe unten) Index, der die Länge der Innenabmessung entspricht: Vergleich und bestimmte Adressenarithmetik (andere erlaubt Einschränkungen gelten!).
    • der äußere Index ist gleich der Länge der äußeren Dimension, und der innere Index ist 0: Das gleiche.
  • Alles andere: Die Adresse ist ungültig und jede Nutzung (nehmen Sie Adresse, dereferenzieren, etc.) ruft undefinierten Verhalten.

Was genau in Erinnerung geht vielleicht ein bisschen mehr klar werden, wenn wir unterschiedliche Längen für die Abmessungen verwenden und einen Blick, wie die Daten gespeichert werden:

int arr[3][2]; 

Dies ist ein " Array von 3 Arrays von 2 int Elementen ".Die am weitesten links liegende Dimension ist die „äußere“, die am weitesten rechts der „innere“ Dimension, wegen der Speicherlayout genannt:

arr[0][0] // row 0, column 0 
arr[0][1] // row 0, column 1 
arr[1][0] // ... 
arr[1][1] 
arr[2][0] 
arr[2][1] 

der obigen Formel Verwendung, &arr[0][2] (arr + 0 * 2 + 2) die gleiche wie &arr[1][0] (arr + 1 * 2 + 0) ergeben, usw. Beachten Sie jedoch, während die Adressen identisch sind, die erste Version nicht dereferenziert werden und der Compiler möglicherweise falschen Code usw.