== für Zeigervergleich

Lesezeit: 6 Minuten

Ich zitiere aus “The C Programming Language” von Kernighan & Ritchie:

Jeder Zeiger kann sinnvoll auf Gleichheit oder Ungleichheit mit Null verglichen werden. Aber das Verhalten ist undefiniert für Arithmetik oder Vergleiche mit Zeigern, die nicht auf Mitglieder desselben Arrays zeigen. (Es gibt eine Ausnahme: Die Adresse des ersten Elements nach dem Ende eines Arrays kann in der Zeigerarithmetik verwendet werden.)

Heißt das, ich kann mich nicht darauf verlassen? == um die Gleichheit verschiedener Zeiger zu überprüfen? In welchen Situationen führt dieser Vergleich zu einem falschen Ergebnis?

  • Wenn Sie verschiedene Arten von Zeigern haben und sie den gleichen Wert haben, dann zeigen sie auf die gleiche Speicheradresse und Sie könnten ein kleines Problem haben. Aber wie auch immer, es ist normalerweise in Ordnung, Zeiger zu vergleichen, wenn Sie sich absolut sicher sind, dass das Speicherlayout vollständig linear ist. Ansonsten nein. Denken Sie an einen 8086.

    – Herr Lister

    3. April 2012 um 13:30 Uhr


Ein Beispiel, das mir in den Sinn kommt, ist die Harvard-Architektur mit getrennten Adressräumen für Code und Daten. In Computern dieser Architektur kann der Compiler speichern Konstante Daten im Codespeicher. Da die beiden Adressräume getrennt sind, ein Zeiger auf eine Adresse im Codespeicher könnte numerisch gleich einem Zeiger im Datenspeicher sein, ohne auf dieselbe Adresse zu zeigen.

  • Diese Antwort könnte umformuliert werden als „in C-Compilern, die sich nicht an den ISO-C-Standard halten“.

    – chazomaticus

    3. April 2012 um 21:22 Uhr

  • Diese Antwort ist für C irrelevant, da Objekt- und Funktionszeiger nicht direkt vergleichbar sind und die Konvertierung zwischen ihnen nicht definiert ist. Ohne implementierungsspezifische Hacks gibt es keine sinnvolle Möglichkeit, einen Funktionszeiger mit einem Objektzeiger zu vergleichen. Und wie Chazomaticus betont hat, ist es für einen Compiler für eine Harvard-Architektur unmöglich, Daten im Codesegment zu speichern.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    3. April 2012 um 23:09 Uhr


  • @R.. In den frühen neunziger Jahren arbeitete ich mit einem 8051 C-Compiler, in dem Sie Konstanten platzieren können Code Erinnerung. Ich erinnere mich nicht, ob es eine Compiler-Erweiterung erforderte oder einfach ein const-Array deklarieren würde, aber ich erinnere mich, dass ich eine bekommen konnte char* und const char* zeigt auf anders Arten von Erinnerungen. Es gab auch eine spezielle Art von Zeigern, mit denen Sie zur Laufzeit auf die eine oder andere Art von Speicher zeigen konnten, die jedoch drei Bytes anstelle der üblichen zwei erforderte. Das ist eine Weile her, der Standard lag bestenfalls bei C89.

    – Sergej Kalinitschenko

    3. April 2012 um 23:22 Uhr

  • Dann ist das kein C-Compiler. C erlaubt const char * um auf nicht konstante Daten zu zeigen (dies ist eine normale Verwendung und hat sogar eine implizite Konvertierung) und erlaubt es auch char * auf konstante Daten zeigen, solange sie nicht zum Ändern dieser Daten verwendet werden. Der Typ des Zeigers darf die Position, auf die er zeigt, nicht ändern.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    3. April 2012 um 23:46 Uhr

  • Das ist nicht “fleckig”. Das ist mit const für einen völlig anderen Zweck als vorgesehen und kaputt irgendein Programm, das verwendet const nicht trivial. Auch die Standardbibliothek funktioniert nicht (strlen nimmt ein const char * und konnte die Länge eines Nicht-const Schnur…).

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    4. April 2012 um 0:45 Uhr

Der Gleichheitsoperator ist für alle gültigen Zeiger definiert und kann nur dann ein “falsch positives” Ergebnis liefern, wenn ein Zeiger auf ein Element hinter dem Ende eines Arrays zeigt und der andere zufällig darauf zeigt (oder aufgrund von a Strukturdefinition) zu einem anderen Objekt, das direkt hinter dem Array im Speicher gespeichert ist.

Ich denke, Ihr Fehler besteht darin, K & R als normativ zu behandeln. Siehe den C99-Standard (schöne HTML-Version hier: http://port70.net/~nsz/c/c99/n1256.html), 6.5.9 zum Gleichheitsoperator. Das Problem, dass Vergleiche nicht definiert sind, gilt nur für Vergleichsoperatoren (siehe 6.5.8):

Wenn zwei Zeiger verglichen werden, hängt das Ergebnis von den relativen Orten im Adressraum der Objekte ab, auf die gezeigt wird. Wenn zwei Zeiger auf Objekt- oder unvollständige Typen beide auf dasselbe Objekt zeigen oder beide um eins nach dem letzten Element desselben Array-Objekts zeigen, sind sie im Vergleich gleich. Wenn die Objekte, auf die gezeigt wird, Mitglieder desselben Aggregatobjekts sind, sind Zeiger auf später deklarierte Strukturmitglieder größer als Zeiger auf früher in der Struktur deklarierte Mitglieder, und Zeiger auf Array-Elemente mit größeren tiefgestellten Werten sind größer als Zeiger auf Elemente desselben Arrays mit niedrigeren tiefgestellten Werten. Alle Zeiger auf Mitglieder desselben Vereinigungsobjekts sind gleich. Wenn der Ausdruck P auf ein Element eines Array-Objekts und der Ausdruck Q auf das letzte Element desselben Array-Objekts zeigt, ist der Zeigerausdruck Q+1 größer als P. In allen anderen Fällen ist das Verhalten undefiniert.

  • Beachten Sie, dass ISO/IEC 9899:1990 das Ergebnis nicht spezifiziert, wenn ein Funktionszeiger mit einem Objektzeiger verglichen wird.

    – undur_gongor

    3. April 2012 um 14:02 Uhr

  • -1 Das sagen Sie “Der Gleichheitsoperator ist für alle gültigen Zeiger definiert.” dann zitieren Sie den Abschnitt des Standards, der genau das Gegenteil sagt (Beachten Sie, dass Gleichheit als wahr ausgewertet wird, wenn beide auf dasselbe Objekt zeigen; das tut es nicht sagen, die Gleichheit ist falsch, wenn sie auf verschiedene Objekte zeigen).

    – BlueRaja – Danny Pflughöft

    3. April 2012 um 14:42 Uhr

  • +1: erste Antwort, um auf eine Spezifikation zu verweisen. Danny, ich glaube, Sie sind verwirrt: In der zitierten Passage geht es um relationale Vergleiche, nicht um Gleichheitsvergleiche. Der Abschnitt über den Gleichheitsoperator sagt: “Zwei Zeiger vergleichen genau dann gleich, wenn … beide Zeiger auf dasselbe Objekt sind …”. Dies sollte die akzeptierte Antwort sein.

    – chazomaticus

    3. April 2012 um 21:17 Uhr


  • @BlueRaja-DannyPflughoeft: Der von mir zitierte Text betraf andere Operatoren als den Gleichheitsoperator, und ich habe ihn als mögliche Quelle für Missverständnisse angeführt. Der Gleichheitsoperator lässt keine Fehlalarme zu, außer in dem einen Fall, den ich bereits behandelt habe.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    21. Juli 2013 um 16:48 Uhr

Ich interpretiere das wie folgt:

short a[9];
int b[12];
short * c = a + 9;

Hier gilt es, das zu sagen

c > a

Weil c Ergebnisse von a über Zeigerarithmetik,

aber das nicht unbedingt

b == c

oder

c <= b

oder ähnliches, weil sie aus verschiedenen Arrays resultieren, deren Reihenfolge und Ausrichtung im Speicher nicht definiert ist.

Sie können den Zeigervergleich nicht zum Vergleichen von Zeigern verwenden, die auf verschiedene Arrays zeigen.

So:

int arr[5] = {1, 2, 3, 4, 5};

int * p = &arr[0];

int anotherarr[] = {1, 2};

int * pf = &anotherarr[0];

Du kannst nicht tun if (p == pf) seit p und pf zeigen nicht in dasselbe Array. Dies führt zu undefiniertem Verhalten.

Sie können sich auf den Zeigervergleich verlassen, wenn sie auf dasselbe Array zeigen.

Ich bin mir über den arithmetischen Fall selbst nicht sicher.

Benutzer-Avatar
Benutzer2346185

Du kannst tun == und != mit Zeigern aus verschiedenen Arrays.

<, <=, >, >= ist nicht definiert.

1371090cookie-check== für Zeigervergleich

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy