wake-up-neo.net

Wie kann man Zeiger vergleichen?

Angenommen, ich habe 2 Zeiger:

int *a = something;
int *b = something;

Wenn ich sie vergleichen und sehen möchte, ob sie auf dieselbe Stelle zeigen, funktioniert (a == b)?

62
Joey Franklin

Ja, das ist die Definition der Zeigergleichheit: Beide zeigen auf dieselbe Position (oder sind Pointer-Aliasnamen )

50

Für ein bisschen facts hier der relevante Text aus den Spezifikationen

Gleichheitsoperator (==,! =)

Zeiger auf Objekte desselben Typs können zur Gleichheit mit den "intuitiven" erwarteten Ergebnissen verglichen werden:

Aus § 5.10 des C++ 11-Standards:

Zeiger desselben Typs (nach Zeigerumwandlungen) kann auf Gleichheit verglichen werden. Zwei Zeiger desselben Typs sind gleich, wenn und nur wenn beide null sind, zeigen beide auf dieselbe Funktion oder beide stellen dieselbe Adresse dar (3.9.2).

(lässt Details beim Vergleich von Zeigern auf Member und oder der Nullzeiger-Konstanten aus - sie setzen sich in derselben Zeile fort wie "Was ich meine") :)

  • [...] Wenn beide Operanden null sind, sind sie gleich. Andernfalls, wenn nur eine Null ist, vergleichen sie ungleich. [...] 

Die "auffälligste" Einschränkung hat mit virtuellen zu tun, und es scheint auch logisch zu sein:

  • [...] Wenn einer der Zeiger auf eine virtuelle Memberfunktion ist, ist das Ergebnis nicht angegeben. Ansonsten haben sie vergleichen Sie genau dann, wenn und nur dann, wenn sie sich auf dasselbe Element des gleichen abgeleiteten Objekts beziehen würden (1.8) oder dasselbe Unterobjekt, wenn sie mit einem hypothetischen Objekt des zugehörigen Klassentyps dereferenziert wurden. [...] 

Vergleichsoperatoren (<,>, <=,> =)

Aus § 5.9 des C++ 11-Standards:

Zeiger auf Objekte oder Funktionen desselben Typs (nach Zeigerkonvertierungen) können verglichen werden mit einem Ergebnis, das wie folgt definiert ist:

  1. Wenn zwei Zeiger p und q desselben Typs auf dasselbe Objekt oder .__ zeigen. Funktion, oder beide zeigen einen über das Ende desselben Arrays hinaus oder sind beides null, dann geben p<=q und p>=q beide wahr und p<q und p>q beide falsch.
  2. Wenn zwei Zeiger p und q desselben Typs auf verschiedene Objekte zeigen, sind ..... Keine Mitglieder desselben Objekts oder Elemente desselben Arrays oder auf verschiedene Funktionen, oder wenn nur eine davon null ist, die Ergebnisse von p<q,p>q,p<=q, und p>=qsind nicht angegeben.
  3. Wenn zwei Zeiger auf nicht statische Datenelemente desselben Objekts oder auf .__ zeigen. Unterobjekte oder Array-Elemente solcher Elemente rekursiv den Zeiger auf die später deklariertes Mitglied vergleicht größere Werte, vorausgesetzt, die beiden Mitglieder haben das gleiche Zugangskontrolle (Klausel 11) und sofern ihre Klasse keine Gewerkschaft ist.
  4. Wenn zwei Zeiger auf nicht statische Datenelemente desselben Objekts mit .__ zeigen. Bei einer anderen Zugriffskontrolle (Abschnitt 11) ist das Ergebnis nicht spezifiziert.
  5. Wenn zwei Zeiger auf nicht statische Datenelemente desselben Unionsobjekts verweisen, Sie vergleichen gleich (nach der Konvertierung in void*, falls erforderlich). Wenn zwei Zeiger zeigen Sie auf Elemente desselben Arrays oder auf ein Element jenseits des Arrays, das Der Zeiger auf das Objekt mit dem höheren Index vergleicht den höheren Wert.
  6. Andere Zeigervergleiche sind nicht spezifiziert.

Wenn Sie also:

int arr[3];
int *a = arr;
int *b = a + 1;
assert(a != b); // OK! well defined

Auch ok:

struct X { int x,y; } s;
int *a = &s.x;
int *b = &s.y;
assert(b > a); // OK! well defined

Es hängt jedoch von der something in Ihrer Frage ab:

int g; 
int main()
{
     int h;
     int i;

     int *a = &g;
     int *b = &h; // can't compare a <=> b
     int *c = &i; // can't compare b <=> c, or a <=> c etc.
     // but a==b, b!=c, a!=c etc. are supported just fine
}

Bonus: Was gibt es sonst noch in der Standardbibliothek?

§ 20.8.5/8: "Für die Vorlagen greater, less, greater_equal und less_equal führen die Spezialisierungen für jeden Zeigertyp zu einer Gesamtreihenfolge, auch wenn die integrierten Operatoren <, >, <=, >= unterlassen Sie."

Sie können also order einen beliebigen ungeraden void* verwenden, solange Sie std::less<> und Freunde verwenden, und nicht operator<.

86
sehe

Der ==-Operator auf Zeigern vergleicht ihre numerische Adresse und bestimmt, ob sie auf dasselbe Objekt zeigen. 

18
JaredPar

Um zusammenzufassen. Wenn wir sehen wollen, ob zwei Zeiger auf denselben Speicherplatz zeigen, können wir das tun. Auch wenn wir den Inhalt des Speichers vergleichen wollen, auf den zwei Zeiger zeigen, können wir das auch tun.

Wenn wir haben 

int *a = something; 
int *b = something;

das sind zwei Zeiger desselben Typs, die wir können:

Speicheradresse vergleichen:

a==b

und vergleiche den Inhalt:

*a==*b
13
ldgorman

Einfacher Code zum Prüfen des Zeigeraliasing:

int main () {
    int a = 10, b = 20;
    int *p1, *p2, *p3, *p4;

    p1 = &a;
    p2 = &a;
    if(p1 == p2){
        std::cout<<"p1 and p2 alias each other"<<std::endl;
    }
    else{
        std::cout<<"p1 and p2 do not alias each other"<<std::endl;
    }
    //------------------------
    p3 = &a;
    p4 = &b;
    if(p3 == p4){
        std::cout<<"p3 and p4 alias each other"<<std::endl;
    }
    else{
        std::cout<<"p3 and p4 do not alias each other"<<std::endl;
    }
    return 0;
}

Ausgabe:

p1 and p2 alias each other
p3 and p4 do not alias each other
1