2017-01-14 2 views
4
double a=4; 
double *x=&a; 
double **y=&x; 
cout <<x<<endl<<(y+1)<<endl<<(y+1)[0]<<endl<<y[1]; 

Wenn ich die oben C++ Code ausführen, wird der Ausgang sein:ein qestion über Zeiger auf Zeiger

0x28fef0

0x28fef0

I weiß, der Wert von x ist die Adresse der Variablen a, und der Wert von y ist die Adresse der Variablen x. aber wie kommt x = y + 1? Was bedeuten y + 1, (y + 1) [0] und y [1]? Danke für jede Hilfe!

+0

'(y + 1) [0]' und 'y [1]' rufen undefiniertes Verhalten auf. – UnholySheep

+0

@Sash Wie haben Sie vier Werte erhalten, wenn die Anweisung nur drei Werte ausgibt? :) –

+1

"Wie kommt x = y + 1"? Was ist das Problem? Zwei Variablen befinden sich nebeneinander im Speicher, so dass ihre Adressen nicht nahe beieinander liegen. – AnT

Antwort

1

Dinge wissen wir über die Variablen:

  • a eine Doppel

  • & ein einen Zeiger auf eine (double *) ist

  • x ist ein Zeiger auf Element/e vom Typ double.

  • x initialisiert wird, um einen Punkt zu, speichert er eine Adresse (& a)

  • & x ist ein Zeiger auf x (Doppel **)

  • y ein Zeiger auf Zeiger/s

  • y initialisiert zu verdoppeln, wird auf x verweisen, speichert er x-Adresse (& x)

Nun, über den Ausdrücken:

  • y + 1 inkrementiert der Zeiger in der Größe des Elements zeigte auf, das ist, die Größe eines Zeigers.

  • y [0] das erste Element der Anordnung von y zeigte auf. y Punkte auf einen Skalar, der als ein Feld von der Größe 1 Elemente in diesem Fall verhält. Es ist völlig äquivalent zur Dereferenzierung von y (* y). So, Y [0] == == y * x

  • ähnlich y [1] == * (y + 1). Da es in dem „Array“, auf dem durch y, dieser Ausdruck löst undefiniertes Verhalten kein zweites Element ist. Im Idealfall würde dies zu einer Ausnahme führen, aber undefined bedeutet alles. Es kann auch das Universum zerstören, und es wäre eine konforme Implementierung.

  • (y + 1) [0] inkrementiert y und referenziert es, so (y + 1) [0] == * (y + 1) == y [1]. Es entspricht dem vorherigen und löst das gleiche undefinierte Verhalten aus.

Nun ist die Adresse einer Variablen vollständig implementierungsabhängig. Es kann auch bei jeder Ausführung anders sein.

Diese Variablen sind automatische Variablen, die in dem Stapel gespeichert sind.

In allen Implementierungen, die ich kenne, beginnt der Stapel in einer hohen Adresse und wächst nach unten.

Dies bedeutet, dass alle automatischen Variablen im selben Block zusammen in abnehmender Adressreihenfolge gespeichert werden.

In Ihrem Fall weist der Compiler die Variablen im Stapel in derselben Reihenfolge zu, in der sie deklariert sind.

Das Ergebnis ist, dass & a> & x> y &

Der Compiler Lücken in der Mitte für alingment Zwecke einführen kann. In diesem Fall tut es auch nicht so, oder es berücksichtigt sie in Zeigerarithmetik.

Also, wie y auf x zeigt, wenn Sie 1 zu y hinzufügen, erhalten Sie die Adresse von a, die neben x befindet.

x verweist auch auf ein, so dass Sie versucht fühlen, dass y + 1 == zu sagen x

In was kommt in den Rohadressen das ist wahr, aber nicht, wenn es darum geht, Zeiger, weil sie es nicht sind vom gleichen Typ.

y + 1 ist immer noch ein Doppel ** während x ein double *

ist

Wir wissen, dass (y + 1) [0] == y [1]. Während x [0] == a, versucht y [1] den Wert von a als Zeiger auf double zu interpretieren. Sie könnten in diesem Fall sagen, dass y [1] == (double *) ein

Sieht aus wie all dieses nicht definiertes Verhalten, in dieser Implementierung Ergebnisse den Wert 4.0 als Null-Zeiger in der Interpretation, ausgedruckt als 0

+0

Vielen Dank für die ausgezeichnete Antwort! – sash

9

wie kommt x = y + 1?

Durch Zufall. Ihr Compiler passiert x und y im Speicher so, dass man dem anderen sofort folgt. Es ist dazu nicht verpflichtet, so dass Sie sich nicht auf dieses Verhalten verlassen können.

Beachten Sie, dass y+1, zum Beispiel durch (y+1)[0], y[1] oder *(y+1) dereferencing, hat auch undefined behaviour.

1
  • a ein Integer-Variable, dessen Wert 4.
  • x ist ein Zeiger auf eine ganze Zahl, die die Adresse a enthält.
  • y ist ein Zeiger auf einen ganzzahligen Zeiger, d. H. Er zeigt auf eine Variable, die ein ganzzahliger Zeiger selbst ist, und hier ist ihr Wert die Adresse x. Jetzt

,

  • Wenn Sie den Wert von x drucken, druckt er die Adresse heraus, es enthält, das heißt, die Adresse des a.
  • y enthält die Adresse x. y+1 ist die Adresse neben der in y gespeicherten Adresse. Hier stellt sich zufällig heraus, dass die in y gespeicherte Adresse kurz vor der Adresse a und damit y+1=x lag. Es gibt keinen Grund dafür.
  • (y+1)[0] und y[1] sind die gleichen wie *(y+1). Diese Dereferenzierung, d. H. Ergibt den gespeicherten Wert bei der Adresse neben y, was ein undefiniertes Verhalten ist.
+0

Ich glaube nicht, dass es ein Zufall ist, dass y + 1 = x – Juan

+0

Sorry, ich habe es versucht um eine neue Antwort zu schreiben – Juan