2016-12-07 6 views
1

Das folgende Programm gibt -1, aber ich erwartete es 1 drucken:Warum bekomme ich eine negative Zahl beim Subtrahieren von Zeigern?

#include <iostream> 
int main() 
{ 
    int a[] = {0, 1}; 
    int* p = a; 
    int* p2 = a+1; 

    std::cout << p - p2 << std::endl; 
    system("PAUSE"); 
    return 0; 
} 

Wenn ich die Subtraktion wie folgt tauschen um:

std::cout << p2 - p << std::endl; 

Dann bekomme ich genau 1.

Die Antwort auf Pointer subtraction confusion sagt, dass, wenn wir Zeiger von Zeigern subtrahieren, wir die Menge der Speicherblöcke zwischen ihnen liegenden bekommen, und ich sehe nicht, dass diese negativ sein kann.

Ich erwarte, genau das gleiche Ergebnis für p - p2 und p2 - p zu erhalten.

+0

Sie sollten 'p' von' p2' subtrahieren, nicht umgekehrt. -1 ist richtig für das, was Sie haben (ein Speicherblock vom ersten Block, Null-Nummer). – Resurrection

+0

Aus Gründen des Experiments habe ich versucht, umzukehren, und ich mag die Antwort, die ich bekomme, aber wenn ich die erste mache, die mir -1 gibt, bin ich verwirrt. Was bedeutet -1? –

+0

sagen wir eine [0] Adresse ist 0x01, a [1] ist 0x02, also p - p2 ist 1 - 2 ist -1 – Lukasz

Antwort

3

Sie subtrahieren p2 (Zeiger auf das zweite Element) von p (Zeiger auf erstes Element). Nehmen wir an, ist Speicheradresse, die der Zahl 1000 entspricht (wenn sie in int konvertiert wird). p2 dann wird 1000 + sizeof(int) oder 1004 auf den meisten Systemen sein. Pointer-Arithmetik:

(address - address2)/sizeof(T)

wo T ist Ihre Art. Deshalb, wenn Sie tun:

p - p2 //(1000 - 1004)/4

Sie -1 erhalten. Wenn Sie das Gegenteil tun, erhalten Sie 1.

+0

@MM Fundamentaler Typ in C++ ist Byte. Wenn Sie mit Zeigern zu größeren Typen (wie "int") arbeiten, sehen Sie z.B. 'p1' ist' 1505216' und 'p2' ist' 1505220'. Sie werden also erwarten, dass Sie 4 oder -4 erhalten, wenn Sie sie addieren oder subtrahieren. Stattdessen erhalten Sie 1 und -1. Hä? Und dann sagt dir jemand, mach dir keine Sorgen, es ist Zeigerarithmetik (aka Magie) und es funktioniert so. Oder vielleicht versuchst du zu erklären, was passiert und du kannst natürlich hinzufügen, dass der Standard dieses Verhalten vorschreibt und dies ist der üblichste Weg, wie es gemacht wird. Sie können die Erklärung als unnötiges Detail betrachten. Da sind wir nicht einverstanden. – Resurrection

+0

Ich erwarte, dass, wenn ich '& a [0]' und '& a [1]' subtrahiere, "-1", unabhängig davon, wie jeder Zeiger im Speicher gespeichert wird. Das liegt daran, dass ich die Regeln von C++ kenne. Ihr letzter Kommentar zeigt genau die Gefahr, dass sich ein Verständnis auf Implementierungsdetails gründet: Es führt zu falschen Erwartungen. Es gibt nichts Kompliziertes und nichts Magisches an der Regel "& a [X] - & a [Y] == X - Y". Ihre Erklärung fügt entweder unnötige Komplikationen hinzu (auf einem System, das die Implementierungsdetails enthält, auf die sich Ihre Antwort bezieht) oder ist falsch (auf einem System, das keine Zeiger auf diese Weise speichert). –

-3

Pointer ist nur eine Adresse oder eine Zahl mit doppelter Schriftgröße (in den meisten Fällen) so OFC, wenn Sie eine zu p hinzufügen, dann wird der Unterschied sein ..

+0

Bitte erkläre die down voice .. –

+0

Ich bin noch nicht downvotiert ... aber deine Antwort ist falsch und widersprüchlich. Sie müssten den Zeigertyp umwandeln (um 'char *' sagen), um die Anzahl der Bytes Unterschied zu erhalten, wie Sie sagen. Und auf der einen Seite sagen Sie natürlich, der Unterschied ist eins und dann sagen, es ist die Anzahl der Bytes. – PeterSW

+0

Der Zeiger ist als int definiert, so dass ich es nicht werfen muss. –

2

Sie erhalten -1, denn das ist die Menge, die Sie p2 hinzufügen müssen, um p zu erreichen. Subtraktion ist die umgekehrte Addition.

Zeigerarithmetik funktioniert in Einheiten des spitzen Typs, in diesem Fall int. wird auf a[0] und p1 Punkte auf a[1] zeigen. Mit anderen Worten, p + 1 == p2 und p2 - 1 == p.

Zeiger-Typen in C++ sind eine Abstraktion, und wie alle Abstraktionen ist es am besten (die meiste Zeit), die Abstraktion zu verwenden - in diesem Fall müssen Sie sich nicht um Maschinenadressen und die Größe der Typen kümmern Zeigerarithmetik. Wenn Sie sicherstellen, dass der Typ korrekt ist, können Sie Arrays einfach durch die Anzahl der Elemente durchlaufen, unabhängig von ihrer Größe.

Es ist nützlich zu verstehen, wie die Abstraktion von der Maschine implementiert wird, und wichtig zu wissen, wann Sie unter die Abstraktion schauen müssen; Solche Situationen umfassen union Arten und die Verwendung von reinterpret_cast<>().

+0

"Es ist normalerweise am besten, sich nicht um Maschinenadressen und die Größe der Typen bei der Zeigerarithmetik zu kümmern" - 100% stimmen zu. – davmac

+0

@davmac Ich stimme respektvoll nicht zu. OP fragte nach Erklärungen, wie die Zeigerarithmetik funktioniert. Diese Antwort sagt "Es ist normalerweise am besten, sich nicht um Maschinenadressen und die Größe von Typen zu kümmern, wenn man Zeigerarithmetik durchführt". Wie beantwortet das die Frage? Oder dem OP helfen, das Thema zu verstehen? Oder Sie glauben wirklich, dass OP unserem Wort vertrauen sollte, dass es funktioniert und sich nicht darum kümmern, wie und warum es so funktioniert? Größe der Typen und Maschinenadressen sind die Dinge, die es erklären. – Resurrection

+1

Vielleicht habe ich Dinge falsch formuliert. Die Zeigertypen von C++ sind eine Abstraktion. Wie bei allen Abstraktionen ist es hilfreich, ein Verständnis dafür zu haben, wie die Abstraktion implementiert wird, aber * die meiste Zeit * sollte man sich auf die Abstraktion stützen und ihre Arbeit machen können. (und Sie sollten wissen, wann Sie unter die Abstraktion schauen müssen) –

1

aus der Standarddefinition des Zeigers Subtraktionsergebnis ++ C:

Wenn zwei Zeiger auf die Elemente des gleichen Array-Objekt subtrahiert werden, ist das Ergebnis die Differenz der Indizes der zwei Array-Elemente.

"Differenz" bedeutet Subtraktion. Also im Code sagt das, dass &arr[X] - &arr[Y]X - Y ist. Dies kann positiv oder negativ sein, abhängig davon, ob X oder Y größer ist.

In Ihrem Code a bedeutet &a[0], und a+1 bedeutet &a[1]. Also, wenn Sie tun a - (a+1) ist es das gleiche wie &a[0] - &a[1], die -1 nach der obigen Regel ist.

Verwandte Themen