C/C++: Zeiger-Arithmetik
War ich noch ein wenig Lesen in der Zeiger-Arithmetik, und ich kam auf 2 Dinge, die ich nicht verstehen konnte weder wissen, dass es die Verwendung
address_expression - address_expression
und auch
address_expression > address_expression
Kann jemand bitte erklären Sie mir, wie Sie funktionieren und Wann Sie eingesetzt werden.
Edit:
Was ich sagen wollte, ist, was Sie produzieren, wenn ich nur zwei Adressen, und Sie ziehen Sie
Und Wenn ich zwei Adressen ein und vergleichen Sie, was ist das Ergebnis bzw. der Vergleich basiert auf
Bearbeiten:
Jetzt verstehe ich das Ergebnis der Subtraktion-Adressen, aber der Vergleich der Adressen, die ich noch nicht bekommen.
Ich verstehe, dass 1<2, aber wie wird eine Adresse größer als andere und was sind Sie im Vergleich auf
- Titel ankündigt, C++ , noch tags enthält C,C++. Wenn das Ziel ist, duale Sprache mit einer zwei-Sprachen-Lösung, die den Titel abnehmen sollte C++.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Zeiger Subtraktion liefert die Anzahl der array-Elemente zwischen den beiden Zeigern des gleichen Typs.
Beispielsweise
Pointer-Vergleich. Zum Beispiel, für die
>
relationalen operator: die>
Betrieb Erträge1
wenn die Spitzen array-element oder Struktur-Element auf der linken Seite ist nach dem Spitzen array-element oder Struktur-Element auf der rechten Seite und es ergibt0
sonst. Denken Sie daran arrays und Strukturen sind geordnete Sequenzen.-
und>
nur Arbeit für die Zeiger in der gleichen array. Es ist Undefiniertes Verhalten und verwenden Sie diese für etwas anderes.Mehrere Antworten hier haben erklärt, dass die Zeiger sind zahlen. Dies ist nicht eine genaue Beschreibung der Zeiger wie angegeben durch den C-standard.
Großen Teil, die Sie an denken können Zeiger als zahlen, und als Adressen im Speicher, vorausgesetzt (a) Sie verstehen, dass die Zeiger Subtraktion wandelt die Differenz von bytes an, die Elemente (der Typ der die Zeiger abgezogen), und (b) Sie verstehen die Grenzen, wo dieses Modell in den Pausen.
Folgende Verwendungen 1999 C standard (ISO/IEC 9899, Zweite Ausgabe 1999-12-01). Ich erwarte das folgende ist Ausführlicher als die Fragesteller gebeten, aber, da einige der Fehler hier, ich beurteilen, dass präzise und genaue Angaben gegeben werden sollte.
Pro 6.5.6 Absatz 9 können Sie subtrahieren zweier Zeiger, die auf Elemente des gleichen Arrays oder einer hinter das Letzte element des Arrays. Also, wenn Sie
int a[8], b[4];
können Sie subtrahieren Sie einen Zeiger auf a[5] von Zeiger auf a[2], denn[5] und[2] sind die Elemente in ein und demselben array. Sie können auch subtrahieren Sie einen Zeiger auf a[5] von Zeiger auf a[8], weil ein[8] ist eine Vergangenheit, die das Letzte element des Arrays. (ein[8] ist nicht im array; a[7] ist das Letzte element ist.) Sie kann nicht subtrahieren Sie einen Zeiger auf a[5] von Zeiger auf b[2], denn[5] ist nicht im gleichen array als b - [2]. Oder, genauer gesagt, wenn Sie eine solche Subtraktion, ist das Verhalten undefiniert. Beachten Sie, dass es ist nicht nur das Ergebnis, dass nicht angegeben ist, kann man nicht erwarten, dass Sie einige möglicherweise unsinnige Zahl als Ergebnis: Die Verhalten ist nicht definiert. Gemäß dem C-standard, das bedeutet, dass der C-standard sagt nichts über das, was geschieht als Folge. Ihr Programm könnte Ihnen eine vernünftige Antwort, oder es könnte Abbrechen, oder es könnte das löschen von Dateien, und alle diese Folgen würden in Konformität zum C-standard.Wenn Sie einem erlaubt, die Subtraktion, dann wird das Ergebnis ist die Anzahl der Elemente aus der zweiten spitz-element, um die ersten Spitzen-element. So
a[5]-a[2]
3 unda[2]-a[5]
ist -3. Dies gilt unabhängig davon, welche Arta
ist. Die C-Implementierung erforderlich ist, konvertieren Sie die Entfernung von bytes (oder was auch immer Einheiten verwendet) in die Elemente des entsprechenden Typs. Wenna
ist ein array von double acht bytes, danna[5]-a[2]
3, für 3 Elemente. Wenna
ist ein array von char ist ein byte, danna[5]-a[2]
3, für 3 Elemente.Warum würde der Zeiger nicht immer nur zahlen? Auf einigen Computern, vor allem ältere Computer, die Adressierung der Speicher war komplizierter. Die ersten Computer hatten kleine Adressräume. Wenn die Hersteller wollten, um größere Adressen ein Leerzeichen, Sie wollten auch pflegen einige die Kompatibilität mit Alter software. Sie hatte auch zur Umsetzung verschiedener Regelungen, die für die Adressierung von Speicher, aufgrund von hardware-Beschränkungen, und solche Systeme haben können, beteiligt sind, verschieben von Daten zwischen Speicher und Festplatte oder ändern von speziellen Register in dem Prozessor gesteuert, wie die Adressen umgewandelt wurden, um physische Speicheradressen. Für Hinweise zu arbeiten an Maschinen wie, dass, Sie enthalten mehr Informationen als nur eine einfache Adresse. Weil dieses, die C-standard nicht einfach definieren, Zeiger, Adressen und lassen Sie rechnen mit Ihnen. Nur eine angemessene Menge der Arithmetik definiert ist, und die C-Implementierung ist erforderlich, um die notwendigen Operationen zu machen, dass die arithmetischen arbeiten, aber nicht mehr.
Sogar auf modernen Maschinen, kann es zu Komplikationen kommen. Auf Digital Alpha Prozessoren, einen Zeiger auf eine Funktion enthält nicht die Adresse der Funktion. Es ist die Adresse des Deskriptors, der von der Funktion. Dass descriptor enthält die Adresse der Funktion, und es enthält einige zusätzliche Informationen, die notwendig ist, um die Funktion aufzurufen richtig.
Bezug auf Vergleichsoperatoren wie
>
, der C-standard sagt, in 6.5.8 Absatz 5, dass Sie vergleichen die gleichen Hinweise, die Sie subtrahieren kann, wie oben beschrieben, und Sie können auch vergleichen Zeiger auf Elemente einer aggregierten Objekt (struct oder union). Zeiger auf Elemente einer Matrix (oder Ihr Ende-Adresse) zu vergleichen, in der erwarteten Weise: Zeiger auf höher indizierten Elementen, die größer sind als Zeiger zu senken-indizierten Elementen. Zeiger auf zwei Mitglieder der gleichen Gewerkschaft Vergleich gleich. Für Hinweise, die zu zwei Mitglieder eine Struktur, die pointer auf die member später erklärte, der größer ist als der Zeiger auf das Mitglied zuvor deklariert.Wie lange Sie bleiben innerhalb der Begrenzungen oben, dann Sie können denken, der Zeiger als zahlen, die Speicher-Adressen.
Normalerweise ist es einfach für eine Umsetzung in C zu bieten, das Verhalten erforderlich, durch den C-standard. Auch wenn ein computer eine Verbindung Zeiger-Schema, wie eine Basisadresse und offset, in der Regel alle Elemente eines Arrays wird mit der gleichen Basis-Adresse, wie jedes andere, und alle Elemente eines struct wird mit der gleichen Basis-Adresse, wie jedes andere. So kann der compiler einfach subtrahieren oder vergleichen Sie die offset-Teile der Zeiger auf den gewünschten Unterschied oder Vergleich.
Jedoch, wenn Sie subtrahieren von Zeigern auf verschiedene arrays auf einem computer verwenden, können Sie bekommen seltsame Ergebnisse. Es ist möglich, das bit-Muster gebildet durch eine Basisadresse und offset angezeigt werden, größer (wenn Sie interpretiert wird als eine ganze Zahl) als einen anderen Zeiger auch wenn es Punkte zu einer niedrigeren Adresse im Speicher. Dies ist ein Grund, Sie muss sich innerhalb der Regeln durch den C-standard.
ptrdiff_t
? Einuintptr_t
? Etwas anderes?ptrdiff_t
.Subtraktion zweier Zeiger-Adressen liefert die Anzahl der Elemente der Typ.
Also, wenn Sie ein array von ganzen zahlen und zwei Zeiger in es, subtrahieren diejenigen, die Zeiger zurückgeben der Anzahl von int-Werten zwischen nicht die Anzahl der bytes. Gleiche mit char-Typen. So müssen Sie vorsichtig sein mit dieser, vor allem, wenn Sie arbeiten mit einem byte-Puffer-oder wide-Zeichen, dass Ihr Ausdruck ist die Berechnung der richtige Wert. Wenn Sie brauchen, byte-basierten buffer-offsets für etwas, das nicht mit einem einzigen byte für die Speicherung (int, short, etc.), die Sie brauchen, um werfen Sie Ihre Zeiger auf char* erste.
char
Arten, Subtraktion immer zählt bytes, weilchar
ist definiert als ein byte durch den C-standard.p1 - p2
undp1 < p2
ist undefiniert, wenn die beiden Zeiger nicht auf Unterobjekte innerhalb der gleichen superobject (Elemente im array).Zeiger können oft gedacht werden als nur zahlen, stellt die Speicher-Adresse, wie 0x0A31FCF20 (oder 2736770848 in dezimal), oder 0xCAFEDEAD (manchmal-Systeme verwenden diese, um anzuzeigen, ein Fehler, ich kann mich nicht erinnern, die details.)
Zeiger-Vergleich wird Häufig verwendet, in der Sortierung von arrays von Zeigern. Sortierte arrays von Zeigern sind hilfreich, wenn Sie brauchen, um zu überprüfen, ob ein Zeiger auf eine Liste von Zeigern; wenn die Liste sortiert ist, Sie muss sich nicht durch jedes element der Liste, um herauszufinden, ob der Zeiger in die Liste ein. Sie brauchen, um zu verwenden, um Vergleiche zum Sortieren einer Liste.
Zeiger-Arithmetik wird oft verwendet, wenn Sie einen Zeiger auf ein Datensegment, und Sie brauchen, auf etwas, das nicht an den Anfang des Datensatzes. Zum Beispiel:
Diese ausgeben würde:
Hier bekamen wir die Zeichenfolge, die nach den ersten 6 Zeichen von "Hallo Welt!", oder
"world!"
. Beachten Sie, dass Sie verwenden solltenstd::string
wo verfügbar sein, wird stattdessen, wenn möglich. Ein Konzept sehr ähnlich wie Zeiger-Arithmetik ist random-access-Iteratoren.Subtraktion Zeiger kann Ihnen helfen, den Abstand zwischen diesen beiden Zeigern. Wenn Sie einen Zeiger auf das erste element in einem array und einem Zeiger auf ein element hinter das Letzte element des Arrays durch Subtraktion dieser beiden Zeiger, die Ihnen hilft, finden Sie die Größe des array.
Einem anderen Fall, wo man vielleicht behandeln Zeiger als Integer in einer optimierten version, die von einer verknüpften Liste, die so genannte XOR-verknüpften Liste. Sie können mehr details über es hier. Ich kann erweitern, wenn Sie möchten, lassen Sie mich wissen in den Kommentaren.
Den ersten Ausdruck subtrahiert einen Zeiger von einem anderen. Als einfaches Beispiel, warum dies nützlich sein könnte, sollten Sie einen C-string. Der string ist in zusammenhängenden Speicherbereich, so dass, wenn Sie hatte die Adresse des ersten Zeichens des Strings und die Adresse des letzten Zeichens, die Sie finden konnte, die Länge der Zeichenfolge zu tun:
Solche Zeiger-Arithmetik ist Art bewusst, was bedeutet, dass das Ergebnis der arithmetischen steht für die Anzahl der Elemente - der spezifische Typ - zwischen zwei Zeiger. Im obigen Beispiel mit
char
, der Unterschied ist die Anzahl der Zeichen. Dies funktioniert ähnlich wie z.B. Zeiger auf zweistructs
.Ebenso Ihre zweite Ausdruck ist einfach vergleichen Zeiger und das Ergebnis 1 oder 0. Als ein sehr einfaches Beispiel ist die Adresse des Elements 5 in einem array ist immer
>
die Adresse von element 4:&string[4] > &string[5]
wahr ist.strLength
hat ein off-by-one-Fehler, und es würde nett sein, zu erklären, der Unterschied zwischen C-pointer-Arithmetik und die entsprechende Arithmetik in der Montage, D. H., die Subtraktion von zweiint *
Zeiger wird Ihnen ein anderes Ergebnis, als wenn Sie warf Sie zuchar *
ersten./ % & | ^
) zwei Ganzzahlen miteinander, aber nicht zwei Zeiger.Können Sie behandeln eine Adresse wie eine
int
in vielerlei Hinsicht. Der einzige Unterschied ist der, dassint
ist, die die Anzahl der Größen, die in dieser Adresse. Zum Beispiel, wennint * p
passiert zu haben, den Wert von, sagen wir,234
(von einigen sicher Anweisung von zum Beispielp = new int[12];
), stellt Sie die Adresse, 234. Wenn wir das tunp += 1;
, es ist nur hinzufügen, in Bezug auf die int-Größe. Jetztp
ist (vorausgesetzt, dass 4-byte-int für dieses Beispiel) 238, akap[1]
. In der Tatp[x]
entspricht*(p+x)
. Sie können vergleichen und so genau wie ein int. In manchen zusammenhängen ist es sinnvoll, zum Beispiel in dem gegebenen Beispielp[0]
bezieht sich jetzt auf das, was warp[1]
. Dadurch wird vermieden, etwas zu machen, dasp = &p[1]
welche dereferenziert unnötig.int * p
passiert 234 nach einigen Instruktionen (z.B.p = new int[12];
), können wir tun, Zeiger-Arithmetik mit Sie sicher.