Unterschiedliche Pointer-Arithmetik-Ergebnisse beim Nehmen der Adresse des Arrays

Lesezeit: 5 Minuten

Benutzeravatar von mohangraj
mohangraj

Programm:

#include<stdio.h>

int main(void) {
    int x[4];
    printf("%p\n", x);
    printf("%p\n", x + 1);
    printf("%p\n", &x);
    printf("%p\n", &x + 1);
}

Ausgabe:

$ ./a.out
0xbff93510
0xbff93514
0xbff93510
0xbff93520
$

Ich erwarte, dass das Folgende die Ausgabe des obigen Programms ist. Zum Beispiel:

x        // 0x100
x+1      // 0x104  Because x is an integer array
&x       // 0x100  Address of array
&x+1     // 0x104

Aber die Ausgabe der letzten Anweisung ist anders als ich erwartet hatte. &x ist auch die Adresse des Arrays. Wenn Sie hier also um 1 erhöhen, wird die um 4 erhöhte Adresse gedruckt. Aber &x+1 ergibt die Adresse um 10 erhöht. Warum?

  • Es scheint, dass &x+1 Ihnen die Adresse nach dem Array-Speicher gibt (4*4=16 oder 0x100) …

    – Alnet

    18. November 2015 um 9:09 Uhr


  • Dies ist einer der Fälle, in denen Sie den Unterschied zwischen einem Zeiger und einem Array deutlich sehen.

    – Klas Lindbäck

    18. November 2015 um 9:15 Uhr

  • Wichtige Klarstellung: Diese Adressen sind in Hex. “Um 4 erhöht” bedeutet auch ein 0x4-Inkrement, aber um 0x10 erhöht” meint “um 16 erhöht,” nicht um 10.

    – kdbanman

    18. November 2015 um 17:36 Uhr


  • @LukePark Es sollte eigentlich vom Typ int sein[4]

    – Rationalcoder

  • 18. November 2015 um 21:54 Uhr void * Nur eine Anmerkung (unabhängig von der Frage, die Sie stellen): Ihr Programm hat ein undefiniertes Verhalten (zumindest unter C99), da Sie die Zeiger darauf umwandeln müssen printf bevor Sie sie weitergeben

    (weil es eine variadische Funktion ist). Siehe Drucken von Zeigern in C.

    – schleske

19. November 2015 um 10:09 Uhr
Benutzeravatar von thepace

x -> Points to the first element of the array.
&x ->Points to the entire array.

die Geschwindigkeit Bin hier auf eine anschauliche Erklärung gestoßen:

http://arjunsreedharan.org/post/69303442896/the-difference-between-arr-and-arr-how-to-find

SO link: Warum sind arr und &arr gleich?
Benutzeravatar von i486

i486 0x100 + sizeof x In Fall 4 erhalten Sie sizeof x und sizeof int ist 4 *

= 4 * 4 = 16 = 0x10. sizeof int (Auf Ihrem System

  • ist 4). sizeof int Hinzugefügt

    Schritt, da es von System zu System unterschiedlich ist.

    – Bathseba

18. November 2015 um 9:17 Uhr
Kowshikas Benutzeravatar

Kowshika

Eine einfache Daumenregel, um dies zu bewerten, lautet: Jeder Zeiger auf Inkrement zeigt auf den nächsten Speicherplatz seinerBasistyp

. Der Basistyp von &x ist hier[4] Ganzzahl (*p) die einZeiger auf Array von 4 Ganzzahlen

.

Der nächste Zeiger dieses Typs zeigt also auf eine Entfernung von 16 Bytes (unter der Annahme, dass int 4 Bytes beträgt) vom ursprünglichen Array. x Wenngleich &x und x auf den gleichen Zeigerwert auswerten, sie sind unterschiedliche Typen. Art der int* nachdem es zu einem Zeiger zerfällt &x während Art von int (*)[4]ist

sizeof(x) . sizeof(int)*4ist

. &x Daher der numerische Unterschied zwischen &x + 1 und sizeof(int)*4ist

.

int array[2][4];

Es kann besser mit einem 2D-Array visualisiert werden. Nehmen wir an, Sie haben: array Das Speicherlayout für

array
|
+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+

array[0]        array[1]
|               |
+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+

ist:

int (*ptr)[4] = array;

Wenn Sie einen Zeiger auf ein solches Array verwenden,

ptr             ptr+1
|               |
+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+

und schau dir den Speicher durch den Zeiger an, es sieht so aus: ptr Wie Sie sehen können, ist der Unterschied zw ptr+1 und sizeof(int)*4ist &x . Diese Analogie gilt für den Unterschied zwischen &x + 1 und

in deinem Code.
Benutzeravatar von Bathsheba

Bathseba Ob Sie es glauben oder nicht, das Verhalten Ihres Programms istnicht definiert

&x + 1 ! weist eigentlich darauf hin nur jenseits des Arrays, wie die Antwort von @ i486 geschickt hervorhebt. Sie besitzen diese Erinnerung nicht. Selbst der Versuch, ihm einen Zeiger zuzuweisen, ist ein undefiniertes Verhalten, geschweige denn der Versuch, dies zu tun Dereferenzierung

  • es. int[4]Ich dachte immer, dass dies definiert wurde, da ein Zeiger auf das Ende eines Arrays definiert wurde. Ich denke, es kann anders sein, da dies kein Array von ist

    s, es ist nur eine.

    – chbaker0

  • 18. November 2015 um 11:03 Uhr

    @Bathsheba: Können Sie hier den Standard zitieren? Normalerweise sind Pointer nach dem Ende wohldefinierte Dinge; Warum sollte es in diesem speziellen Fall nicht sein?

    Benutzer1084944


  • 18. November 2015 um 11:57 Uhr

    @Bathsheba: Wie Hurkyl erwähnt, sollte es im Standard einen Klappentext darüber geben, wie “skalare” Objekte als Arrays der Größe 1 zum Zweck von “über das Ende hinausgehenden” Zeigern behandelt werden. Ich würde erwarten, dass dies in diesem Fall zutrifft (da ein Array Arrays enthalten kann), aber der Standard widerspricht regelmäßig meinen Erwartungen.

    – Matthias M.

  • 18. November 2015 um 12:36 Uhr

    @Bathsheba Sie dürfen nicht über das Array hinaus “schauen”, aber IIRC darf diese Adresse ausdrücklich in einem Zeiger speichern. Ich denke, diese Antwort (und andere auf diese Frage) decken dies ab.

    – TripeHound

  • 18. November 2015 um 13:59 Uhr @Bathsheba C11 6.5.6 p7: “Ein Zeiger auf ein Objekt, das kein Element eines Arrays ist, verhält sich genauso wie ein Zeiger auf das erste Element eines Arrays der Länge eins”. Nicht einmal eine Notiz – das ist der Haupttext. (geht unmittelbar dem Zeug über One-Past-the-End voraus) Keine UB hier.

    Skalare sind genau das Gleiche wie Arrays für Zwecke der Zeigerarithmetik.

    – Leuschenko


  • 18. November 2015 um 16:19 Uhr int[4]Ich dachte immer, dass dies definiert wurde, da ein Zeiger auf das Ende eines Arrays definiert wurde. Ich denke, es kann anders sein, da dies kein Array von ist

    s, es ist nur eine.

    – chbaker0

  • 18. November 2015 um 11:03 Uhr

    @Bathsheba: Können Sie hier den Standard zitieren? Normalerweise sind Pointer nach dem Ende wohldefinierte Dinge; Warum sollte es in diesem speziellen Fall nicht sein?

    Benutzer1084944


  • 18. November 2015 um 11:57 Uhr

    @Bathsheba: Wie Hurkyl erwähnt, sollte es im Standard einen Klappentext darüber geben, wie “skalare” Objekte als Arrays der Größe 1 zum Zweck von “über das Ende hinausgehenden” Zeigern behandelt werden. Ich würde erwarten, dass dies in diesem Fall zutrifft (da ein Array Arrays enthalten kann), aber der Standard widerspricht regelmäßig meinen Erwartungen.

    – Matthias M.

  • 18. November 2015 um 12:36 Uhr

    @Bathsheba Sie dürfen nicht über das Array hinaus “schauen”, aber IIRC darf diese Adresse ausdrücklich in einem Zeiger speichern. Ich denke, diese Antwort (und andere auf diese Frage) decken dies ab.

    – TripeHound

  • 18. November 2015 um 13:59 Uhr @Bathsheba C11 6.5.6 p7: “Ein Zeiger auf ein Objekt, das kein Element eines Arrays ist, verhält sich genauso wie ein Zeiger auf das erste Element eines Arrays der Länge eins”. Nicht einmal eine Notiz – das ist der Haupttext. (geht unmittelbar dem Zeug über One-Past-the-End voraus) Keine UB hier.

    Skalare sind genau das Gleiche wie Arrays für Zwecke der Zeigerarithmetik.

    – Leuschenko


1409590cookie-checkUnterschiedliche Pointer-Arithmetik-Ergebnisse beim Nehmen der Adresse des Arrays

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

Privacy policy