2016-06-01 8 views
3

ich diese Frage als eine Klasse Übung gefragt:Printf und Array

int A[] = {1,3,5,7,9,0,2,4,6}; 

printf("%d\n", *(A+A[1]-*A)); 

Ich kann es nicht herausfinden, auf dem Papier, so gingen voran ein einfaches Programm zu kompilieren und es getestet und festgestellt, dass printf("%d",*A) gibt immer Ich 1 für die Ausgabe.

Aber ich verstehe immer noch nicht, warum das der Fall ist, daher wäre es großartig, wenn jemand das erklären könnte.

+0

@abelenky ausgewertet wird: das Ergebnis '1' ist von 'printf ("% d \ n", * A)', das ist was du erwartest, glaube ich. Der ursprüngliche Code würde jedoch "5" erzeugen. Die Frage ist irreführend. –

+1

@abelenky: Steve0101 hat Recht, printf ("% d \ n", * A) druckt immer 1 für das angegebene Array. – babon

+0

Ja, ich habe es falsch gelesen und dachte, er würde 1 für die Ausgabe des größeren Ausdrucks bekommen. Es tut uns leid. Immer noch, Link zu IDEOne, als eine gute Möglichkeit, [MVCE-Code] zu teilen (http://ideone.com/4fu3Sj) – abelenky

Antwort

0

Eine Array-Variable in C ist nur der Zeiger auf den ursprünglichen Speicherort für das Array. Wenn Sie also das Array dererferen, erhalten Sie immer den Wert für die erste Position.

Wenn Sie 1 zum ursprünglichen Array-Wert addieren, wie *(A+1), erhalten Sie die zweite Position.

Sie können eine beliebige Position, die von dem Array bekommen kann mit der gleichen Methode:

*(A) ist die erste Position

*(A+1) der zweiten Position ist

*(A+2) die dritte Position

und so ist on ...

Wenn Sie den Intarr deklarieren ay wie int* A und den Speicher zuweisen und die Werte zuweisen, ist es normalerweise einfacher zu visualisieren, wie dies funktioniert.

+1

Arrays werden automatisch in Zeiger für Dereferenzierung umgewandelt, aber * Arrays sind keine Zeiger! * – MikeCAT

7

A ist behandelt wie ein Zeiger auf das erste Element des Arrays von ganzen Zahlen. A [1] ist der Wert des ersten Elements dieses Arrays, das 3 ist (Indizes sind 0-basiert) * A ist der Wert, auf den A zeigt, was, wenn das nullte Element des Arrays, also 1. So

A[1] - *A == 3 - 1 == 2 

Jetzt haben wir

*(A + 2) 

das ist, wo Zeigerarithmetik in tritt. Da A ein Zeiger auf ganzzahlige, A + 2 Punkten auf den zweiten (0-basiert) Element in dem Array und * (A + 2) erhält seinen Wert. Also die Antwort ist 5.

Bitte beachten Sie auch für zukünftige Referenz, dass Zeiger auf eine ganze Zahl und ein Array von ganzen Zahlen sind etwas andere Dinge in C, aber für die Zwecke dieser Diskussion sind sie das gleiche.

+0

Obwohl es automatisch ist In diesem Ausdruck wird in einen Zeiger umgewandelt, 'A' ist ein * Array *, kein Zeiger. – MikeCAT

+0

@MikeCAT Ja, wie immer ist es sehr verlockend zu lügen und sagen, dass Arrays Zeiger sind. Sie sind fast (für die Zwecke dieser Situation). –

+0

"Wert des ersten Elements" .. nein, Sekunde. –

4

brechen sie in ihre Bestandteile nach unten: die Speicheradresse des ersten Elements des Arrays

A selbst ist die Speicheradresse des Arrays, das zu &A[0] auch gleichwertig ist.

A[1] ist der Wert in dem zweiten Element des Arrays gespeichert ist, die Adresse 3.

*A dereferenziert den Speicher des Arrays ist, das in dem ersten Element des Arrays gespeichert A[0], der Wert wird equivilent , das ist 1.

So haben einige Substitutionen:

*(A+A[1]-*A) 
= *(A+(A[1])-(A[0])) 
= *(A+3-1) 
= *(A+2) 

Die Notation *(Array+index) die gleiche wie die Notation ist Array[index]. Unter der Haube nehmen sie beide die Startadresse des Arrays, inkrementieren sie um die Anzahl der Bytes des Array-Elementtyps (in diesem Fall int) multipliziert mit dem Index und dereferenzieren dann die resultierende Adresse. So ist *(A+2) die gleiche wie A[2], die 5. ist

2
  • Arrays in Ausdrücken verwendet werden automatisch in Zeiger umgewandelt zeigen auf den ersten Elementen der Arrays mit Ausnahme von einigen Ausnahmen wie Operanden von sizeof oder einstelligen & Betreibern.
  • E1[E2] wird definiert *((E1) + (E2))
  • + und - Operator auf Zeiger verwendet äquivalent sein wird, den Zeiger vorwärts und rückwärts zu bewegen.

In diesem Fall ist äquivalent zu *A*(A + 0), die A[0] äquivalent ist, und es wird ihr das erste Element des Feldes geben.

Der Ausdruck *(A+A[1]-*A) wird der Zeiger auf das erste Element

  1. Route, die bei 1 weist über A
  2. den Zeiger auf A[1] Move (3) Elemente voraus über +A[1], so dass der Zeiger nun Punkte bei 7
  3. den Zeiger auf *A (1) bewegen, bevor Element, was über -*A gerichtet ist, so dass nun der Zeiger zeigt auf 5
  4. die Zeiger dereferenzieren über den unären Operator *, so der Ausdruck 5
+0

Ich weiß, was Sie denken, aber ich denke, was verwirrend ist, ist das *" Bewege den Zeiger. "* Satz. Aufgrund der * Operator-Priorität * werden die Werte innerhalb der '(...)' ausgewertet, wobei 'A [1] '(' + 3') und '- * A' (' -1') zum Zeiger 'A hinzugefügt werden vor der Dereferenzierung. So bewegt sich der Zeiger nicht, Sie fügen vor der Dereferenzierung effektiv "2" hinzu. Oder wird ein anderer Zeiger bewegt? –

+0

@ DavidC.Rankin "der Zeiger" hier ist ein rvalue, "den Zeiger bewegen" bedeutet "den Zeiger auf einen anderen Ort zu machen" –

+0

Ja, das ist, was ich es verstanden habe, aber die Wortwolke verursacht noch eine doppelte .. dann triple nehmen, und ein bisschen Kopf kratzen, um einen Sinn die Bedeutung auszuprobieren. Wie es der frühere Kommentar war, war klar, dass Mike kein Problem mit dem Verständnis hatte, aber die Formulierung schien mit der guten Lösung, die er veröffentlichte, in Widerspruch zu stehen. –