Wenn die Verwendung * in pointer-Zuweisung?
Wie Lerne ich C sehe ich oft Hinweise.
Ich, dass ein Zeiger hält den hexadezimalen Wert einer bestimmten Speicherort im Arbeitsspeicher. So ein Zeiger ist nichts anderes als z.B.:0x7fff5fbff85c
Jeden Zeiger ist auch ein eigener Typ.
int var = 10;
int *ptr = &var;
Ptr hier Punkte, um die Lage des var. Um den Wert von var ich habe zu dereferenzieren Sie den Zeiger mit *ptr
.
Wie
printf("Var = %d", *ptr);
drucken würde `Var = 10;
Aber Wenn ich einen nicht-inline-Deklaration eines Zeigers wie:
int var = 10;
int *ptr;
ptr = &var;
Habe ich nicht verwenden Sie die *
in der Dritten Zeile, wenn ich wirklich die Zuordnung der memory-Adresse auf die Zeiger.
Aber wenn ich eine Funktion, die einen Zeiger:
int var = 10;
void assignPointer(int *ptr) {
*ptr = 10;
}
Oh, warten Sie! Da ich dies Schreibe, habe ich erkannt, dass es zwei verschiedene Einsätze für Zeiger:
*ptr = 10;
und
ptr = &var;
Was ist der Unterschied? Bin ich im ersten Fall zuerst die Dereferenzierung der Zeiger zuweisen 10 die Lage, dass Ihr ein festhalten?
Und im zweiten Fall, ich bin die Zuweisung der tatsächlichen Lage auf den Zeiger.
Ich bin ein bisschen verwirrt, Wann der * und wenn nicht in Bezug auf die Zuordnung.
Und wenn ich mich mit arrays zu arbeiten, deshalb brauche ich Zeiger überhaupt?
int array[];
"array" ist hier bereits im Besitz der hexadezimale Speicheradresse. Machen nicht, dass es ein Zeiger? Also, Wenn ich wollte, um etwas zu ordnen array würde ich nicht schreiben:
*array = [10, 2];
Zuerst bin ich dereferenzieren, dann bin ich zuordnen.
Ich bin verloren 🙁
EDIT: Vielleicht ist es ein bisschen unklar.
Ich weiß nicht, wenn Sie müssen, verwenden Sie ein *, wenn Sie arbeiten mit Zeigern ein, wenn nicht.
Alles, was zu tragen ist eine hexadezimale ist ein Zeiger richtig?
Der name der variable ein array ist, tragen Sie die hexadezimale Speicheradresse. Also warum nicht ist es ein Zeiger?
EDIT2: Danke Leute habt mir sehr geholfen!
- Ich sehe eine lange intro-Zeiger hier.. Was ist die Frage? Arrays sind keine Zeiger.
- Bitte starten Sie mit einem guten C-Buch...Sie brauchen das.
- Es gibt entweder zu viele mögliche Antworten, oder eine gute Antwort darauf wäre zu lang für dieses format. Bitte fügen Sie details zu schmal die Antwort setzen oder zu isolieren, ein Problem, das kann beantwortet werden, in ein paar Absätze.
- Grob gesprochen:
x
ist der Wert des Zeigers*x
ist der Wert der Sache wies der Zeiger. Und nicht mixup Deklaration eines Zeigers (int *p;
) und mit dem Zeiger bereits deklariert ist (z.B.*x = 5;
oderx = &value;
) - Die Verwirrung kommt von
int *ptr = &var;
definiertint *ptr
und setzt seinen Wert auf&var
. Wenn Sie bereits definiert den Mauszeiger, weisen Sie es mitptr = &var
. Verwenden Sie die*
zu derefernce den Zeiger, ie auf was es verweist. Soptr
ist vielleicht0xffeebbcc
und*ptr
ist10
. - "Alles, was zu tragen ist eine hexadezimale ist ein Zeiger, richtig?" Nein - es ist keine hexadezimale im inneren der Maschine. Hex ist ein menschlich lesbares format wird beim drucken von einem Zeiger mit der
%p
- format, aber Sie können drucken Sie eineint
im hex auch mit%x
- format. Oh, wait! As I'm writing this I recognized that there are two different assignments for pointers:
Sie lustig sind. 1)*ptr = 10;
undptr = &var;
nichts gemeinsam hat. Es sind zwei verschiedene Dinge. 2) Holen Sie sich ein gutes Buch.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Letzte Sache, die erste - der name eines Arrays ist nicht einen Zeiger; es nicht speichern eine Adresse irgendwo. Wenn Sie definieren ein array, es wird so ausgelegt sein mehr oder weniger wie folgt aus:
Gibt es keine Lagerung beiseite für ein Objekt
arr
getrennt von der array-Elementearr[0]
durcharr[n-1]
. C speichert keine Metadaten wie Länge oder Start-Adresse als Teil des array-Objekts.Statt, es gibt eine Regel, die sagt, wenn ein array Ausdruck erscheint in Ihrem code und, der Ausdruck ist nicht der operand der
sizeof
oder unäre&
Betreiber, wird es konvertiert werden ("decay"), um einen Zeiger Ausdruck, und der Wert der Zeiger-Ausdruck wird die Adresse des ersten Elements des Arrays.So die Erklärung
dann die folgenden Bedingungen erfüllt sind:
Den Ausdrücke
arr
,&arr
, und&arr[0]
alle ergeben die gleiche Wert (die Adresse des ersten Elements des Arrays ist gleich der Adresse des Arrays), sondern Ihre Arten nicht alle gleich;arr
und&arr[0]
TypT *
, während&arr
TypT (*)[N]
(Zeiger aufN
-element-array vonT
).Hexadezimal ist nur eine bestimmte Darstellung von binären Daten; es ist nicht eine Art, in und von sich selbst. Und nicht alles, was geschrieben oder dargestellt in hex ist ein Zeiger. Ich kann den Wert zuzuweisen
0xDEADBEEF
32-bit-Ganzzahl; das heißt nicht, dass es ein Zeiger ist.Die exakte Darstellung von Zeiger können variieren zwischen Architekturen; es kann sogar variieren zwischen verschiedenen Zeiger-Typen auf der gleichen Architektur. Für ein flat-memory-Modell (wie jedes moderne desktop-Architektur), wird es ein einfaches integral Wert. Für eine segmentierte Architektur (wie die alten 8086/DOS-Tagen), könnte es sein, ein paar Werte für die Seite # und offset.
Einen Zeiger Wert darf nicht so breit sein wie die Art verwendet, um es zu speichern. Zum Beispiel, die alten Motorola 68000 hatte nur 24 Adressleitungen, so dass alle Zeiger würde der Wert nur 24 bit breit. Jedoch, das Leben leichter zu machen, die meisten Compiler verwendet 32-bit-Typen zu repräsentieren-Zeiger, verlassen die oberen 8 bit ungenutzt (Potenzen von 2 sind bequem).
Ziemlich einfach - wenn Sie möchten, finden Sie die Spitzen-zu Einheit, verwenden Sie die
*
; wenn Sie möchten finden Sie die Zeiger selbst, lassen Sie es aus.Einen anderen Weg, es zu betrachten - die Ausdruck
*ptr
ist äquivalent zu dem Ausdruckvar
, so dass jede Zeit, die Sie verweisen möchten, zum Inhalt vonvar
verwenden Sie*ptr
.Konkreten Beispiel helfen könnte. Angenommen, das folgende:
Im obigen Beispiel die folgenden Bedingungen erfüllt sind:
Wenn ich etwas dazu schreiben
*p
ich bin wirklich zu aktualisierenvar
. Wenn ich etwas dazu schreibenp
ich werde es, um auf etwas anderes alsvar
.Dieser code oben ist eigentlich der primäre Grund warum Zeiger existieren, an Erster Stelle. In C werden alle Funktionsparameter übergeben werden von Wert; das heißt, die formalen parameter in der Funktionsdefinition ist ein separates Objekt aus der aktuellen parameter im Aufruf der Funktion. Alle updates für die formalen parameter nicht spiegelt sich in der tatsächlichen parameter. Wenn wir den code wie folgt ändern:
Den Wert
p
geändert wird, aber dap
ist ein anderes Objekt im Speicher ausvar
, wird der Wert invar
bleibt unverändert. Die nur Weg für eine Funktion zum aktualisieren der aktuelle parameter wird über einen pointer.Also, wenn Sie aktualisieren möchten, die Sache
p
Punkte zu, schreiben*p
. Wenn Sie festlegen möchtenp
zu Punkt zu einem anderen Objekt, schreibenp
:In diesem Punkt sind Sie wahrscheinlich Fragen, "warum benutze ich die Sternchen in
int *p = &x
und nicht inp = y
?" Im ersten Fall sind wir deklarierenp
als Zeiger und initialisiert ihn in der gleichen operation, und die*
erforderlich ist, durch die Erklärung der syntax. In diesem Fall schreiben wir anp
, nicht*p
. Es wäre äquivalent zu schreibenBeachten Sie auch, dass in einer Erklärung der
*
ist gebunden an den Namen der Variablen, nicht der Typ Bezeichner; es analysiert, wieint (*p);
.C-Deklarationen sind auf der Grundlage der Arten von Ausdrücke, nicht Objekte. Wenn
p
ist ein Zeiger auf einint
, und wir wollen, beziehen sich auf die Spitzen-zu Wert, verwenden wir die*
- operator dereferenzieren es, wie so:Den Typ des Ausdruck
*p
istint
, so die Erklärung geschrieben, wieC-syntax ist komisch, wie diese. Wenn Sie eine variable deklarieren, die
*
ist nur da, um anzuzeigen, der Typ pointer. Es ist nicht wirklich irgendetwas dereferenzieren. So,ist, als ob Sie schrieb
Zeiger deklariert sind, ähnlich wie reguläre Variablen.Das Sternchen vor dem Namen des Zeigers während der Erklärung zu unterscheiden, ist es wie ein Zeiger.Bei der Deklaration sind Sie nicht de-Referenzierung,z.B.:
Nach der Erklärung Anweisung zum zuweisen der Zeiger eine Adresse oder Wert verwenden Sie diesen Namen ohne Sternchen,e.g:
Zuweisen das Ziel des Zeigers ein Wert,Sie dereferenzieren Sie es, indem Sie vor dem Zeiger Namen mit
*
:Dereferenzierter Zeiger ist der Speicher, der es Punkte zu. Nur nicht zu verwechseln mit der Deklaration der Zeiger und es zu benutzen.
Mag es ein wenig leichter zu verstehen, wenn Sie schreiben
*
in der Erklärung bei der Typ:In
Sind Sie ziemlich viel richtig.
Genau. Dies sind zwei logisch unterschiedliche Aktionen, wie Sie sehen.
Und Sie bekommen den Griff auch hier. Für den Willen, Ihr Verständnis würde ich sagen, dass arrays sind Zeiger. In Wirklichkeit ist es jedoch nicht so einfach -- arrays nur Zerfall in Zeiger in den meisten Fällen. Wenn Sie wirklich in diese Angelegenheit, finden Sie ein paar tolle Beiträge hier.
Aber, da es nur ein Zeiger ist, können Sie nicht "assign to array". Zu behandeln, wie ein array im Zeiger-Kontext ist in der Regel erläutert, in der ein ziemlich guter Weg, in jedem C-Buch unter "Strings" Abschnitt.
Sind Sie richtig über den Unterschied zwischen Zuweisung und Dereferenzierung.
Was Sie verstehen müssen ist, dass Ihre array-variable ist ein Zeiger auf das erste element Ihrer kontinuierlichen memory zone
So dass Sie Zugriff auf das erste element von array-Dereferenzierung der Zeiger :
Können Sie Zugriff auf das N-te element durch dereferenzieren einen Zeiger auf das N-te element :
Wo ist die Adresse der pointer auf das erste element plus das offset auf das N-te element (berechnet über die Größe eines Elements in diesem array mal n).
Können Sie auch die entsprechende syntax der Zugriff auf das N-te element :
sizeof
- operator auf ein array: der Rückgabewert ist nicht die Größe eines Zeigers. Siehe stackoverflow.com/questions/1641957/... für mehr.Eines Ihrer Beispiele, ist nicht gültig.
*ptr = 10;
. Der Grund dafür ist, dass 10 einen Wert, aber es ist kein Speicher zugewiesen werden.Können Sie denken Sie an Beispiele wie "die Zuordnung etwas Punkt, an die Adresse" oder "Adresse von etwas ist". So,
int *ptr
ist ein Zeiger auf die Adresse etwas. Soptr = &val;
bedeutet ptr gleich die Adresse von val. Dann kann man sagen*ptr = 10;
oderval = 10;
führen beide *ptr und val sind auf der Suche an der gleichen Speicherstelle und daher den gleichen Wert. (Hinweis: ich habe nicht gesagt, "Hinweis").int val = 10
. Deklarieren Sie einen Speicherbereich, der ist ein int, und legen Sie es auf den 10.int var = 3; int *ptr = &var; *ptr = 9;
Var tritt zuerst 3, dann-ptr-Punkte zu var Position ist, dann wird var ist auf 9 festgelegt durch den Zeiger. Das ist es, was ich meinte. Ich wollte nur nicht schreiben das var-Zuordnung gibt, denn ich habe es in den ersten paar Zeilen.