2016-07-24 7 views
1

Ich wurde "Pointers in C: when to use the ampersand and the asterisk" bei einer Antwort suchen und bin verwirrt über das Beispiel int *p2 = &i; (von Dan Olson Antwort)Wie kann ein C-Zeiger vom Typ int eine Speicheradresse enthalten, wenn eine Byte-Speicheradresse nicht vom Typ int ist?

Die Adresse i ist kein int, dann ist es so etwas wie 0x02304 sagen, nicht wahr? Wie können wir das in p2 setzen? Wie kann ein C-Zeiger vom Typ int eine Speicheradresse enthalten, wenn eine Byte-Speicheradresse nicht vom Typ int ist?

Danke!

P.S. Für jeden, der in diesem Punkt verwirrt ist, ist ein anderer Thread, den ich hilfreich fand (obwohl er diese Frage nicht beantwortet hat) "What exactly is a C pointer if not a memory address" Viel Glück.

+2

'p2' ist kein' int'. Es ist ein * Zeiger auf int *. Alle Zeiger speichern Adressen. Die Größe einer Adresse ändert sich nicht, unabhängig davon, auf was sie zeigt. – kaylum

+1

Würde es helfen, wenn die LHs int * p2 statt int * p2 geschrieben wären? –

+2

@kaylum: Tatsächlich können verschiedene Zeigertypen unterschiedliche Größen haben, aber das ist weit über das Niveau dieser Frage hinaus. – chqrlie

Antwort

0

Ich denke, der Grund int *p2 = &i; ist verwirrend ist der kombinierte Effekt der gleichzeitigen Deklaration und Instanziierung, und der Abstand. Ich erkläre es.

Typischerweise für einen Zeiger-zu-Integer-p2 und eine ganze Zahl i, writing "*p2" Dereferenzierungen p2 und gibt die int&i an der Adresse wohnen.

Also der Code "int *p2 = &i;" macht es wie ein int wird gleich einer Speicheradresse gesetzt.

Tat der Code

int i = 1; 
int *p2; 
*p2 = &i 

ist falsch, denn in der letzten Zeile, *p2 eine int ist, da es p2 dereferenziert ist, und &i ist ein Zeiger.

Warumint *p2 = &i;wird als die letzte Zeile des fehlerhaften Code über die gleiche Sache nicht zu tun:

Den Code int *p2 = &i; oben von den drei Zeilen Code anders ist, weil es eine Erklärung. Wenn Sie eine Zeigervariable deklarieren, setzen Sie den Typ (zB int, long, char usw.) und den Namen Ihrer Variablen (wie üblich) - und Sie setzen auch ein Sternchen * zwischen diesen beiden Teilen (siehe @) chqrlie Antwort oben im Hinblick auf die vielen Abstände Optionen dafür - Takehome ist Best-Practice ist es, die * an den Variablennamen zu halten). In einer Deklaration wird der Zeiger NICHT durch * dereferenziert. Vielmehr teilt es dem Compiler mit, dass die Variable myPointer ein Zeiger auf den Speicher sein wird, der Daten des deklarierten Typs enthält (die int, long, char usw. von zuvor).In dem Bit des Codes "int *p2 = &i;", in dem der Zeiger zur selben Zeit deklariert und instanziiert wird, gibt * keinen int auf der linken Seite aus. Bei Deklarationen ist es sicherer (wie @chqrlie hervorhebt), neben dem Variablennamen den Wert * anzugeben. Dadurch wird der Zeiger nicht ausgepackt, selbst wenn der Zeiger in der Deklaration instanziiert wird. Bei Deklarationen denken Sie an die * als an den Typ (und nicht an den Variablennamen, wo es aus guten Gründen wahrscheinlich ist). Ich mag Zeiger mit den * direkt neben den Zeigernamen erklären, sondern nur zu verstehen, dass, wenn ein Zeiger in der Deklaration instanziiert wird, ein vielleicht klarer Weg für einen neuen Lernende der Linie vorstellbar wäre int* p2 = &1:

int* (Typ pionter-to-int) p2 (Name des Zeigers) = &i (entspricht den Zeiger, der die Adresse des integer i) ;

Vielen Dank an alle, die an alle beantwortet und kommentiert, und viel Glück gibt, die hier sind gekommen, können versuchen, etwas über Zeiger herausfinden.

1

Die Adresse von i ist kein Int, es ist so etwas wie 0x02304 sagen, oder?

Zeiger sind Variablen, die Speicheradressen enthalten. Eine Adresse, genau wie die Adresse Ihres Hauses, ist eine Ganzzahl, die der Position eines Speicherbytes zugeordnet ist.

Wie ein C-Zeiger vom Typ int kann eine Speicheradresse

In Ihrem Beispiel halten, ist p2 Variable vom Typ Zeiger-to-int. Es ist ein Zeiger - eine Speicheradresse -, dem Sie Punkte im Speicher zuweisen, in denen eine int Variable gespeichert wird.

+0

Danke, diese Formulierung ist viel besser. –

+0

Eine Adresse darf keine ganze Zahl sein (genau wie die Adresse Ihres Hauses - die Buchstaben enthält) –

+0

Eine andere Analogie für einen Zeiger ist eine Hotelzimmerkarte, in der eine Zimmernummer gespeichert werden kann, die verwendet werden kann Greife auf den Raum und die Objekte zu, um sie zu sehen oder sogar zu verändern. Die Zimmernummer kann geändert werden, sie kann auch ungültig werden. – chqrlie

1

p2 ist kein int, es ist ein Zeiger auf int. Als solches kann es die Adresse einer int Variablen enthalten.

Die Syntax int *p2; definiert einen Zeiger auf int.

Initialisieren p2 mit &i speichert die Adresse der Variable i in p2. Durch Ändern des Werts, auf den p2 zeigt, wird der Wert i geändert.

die folgenden alternativen Syntaxen sind alle äquivalent:

int *p2 = &i; 
int * p2 = & i; 
int * p2 =& i; 
int*p2=&i; 
int* p2 = &i; 

Die bevorzugte Syntax ist int *p2 = &i; da er ein übliches Mißverständnis vermeidet, wenn mehrere Variablen in derselben Zeile zu definieren:

int *p1, *p2; // defines 2 pointers to int 
int *p1, p2; // p1 is a pointer-to-int, whereas p2 is an int 

die * Wenden zu der Typ macht die letztere Definition sehr unübersichtlich:

int* p1, p2; // p1 is a pointer-to-int, whereas p2 is an int 

Als Konsequenz davon wird auch stark davon abgeraten, Variablen mit unterschiedlichen Indirektionsebenen auf derselben Linie zu definieren.

0

Zeiger sind Abstraktionen von Speicheradressen, mit einigen assoziierten Typ Semantik.

p2 hat Typ int *, oder "Zeiger auf int". Es speichert die Position eines Integer-Objekts (in diesem Fall die Position des Objekts i). Der Typ des Ausdrucks*p2 ist int:

p2 == &i; // both expressions have type int * and evaluate to an address value 
*p2 == i; // both expressions have type int and evaluate to an integer value 

Pointers so groß ist, wie sie einen Adressenwert zu speichern, müssen sie jedoch, dass Adresswert für die gegebene Plattform repräsentiert (ob das ein einziger ganzzahligen Wert oder ein Paar Werte, die eine Seitenzahl und einen Offset oder ein anderes Format darstellen. Beachten Sie, dass verschiedene Zeigertypen unterschiedliche Größen sein können, obwohl sie auf modernen Desktop-Architekturen alle die gleiche Größe haben (32 oder 64 Bit).

Der Typ des Zeigers ist für die Zeigerarithmetik von Bedeutung. Bei einem Zeiger p ergibt der Ausdruck p + 1 die Adresse des nächsten Objekts des spitzen Typs. Wenn der angegebene Typ 1 Byte breit ist (z. B. char) und seine aktuelle Adresse 0x8000 ist, gibt p + 1 die Adresse des nächsten Bytes oder 0x8001. Wenn der Typ 4 Byte breit ist (z. B. long) und die aktuelle Adresse 0x8000 ist, gibt p + 1 die Adresse des vierten nächsten Byte oder 0x8004 zurück.

Verwandte Themen