Entfernt der C-Präprozessor Instanzen von “&*”?

Lesezeit: 5 Minuten

Benutzer-Avatar
evenex_code

Ich habe mit herumgespielt gcc und habe folgenden Code ausprobiert:

int A = 42;
int *B = &A;
int *C = &*B;

Und C == &A, wie erwartet. Aber wenn ich es versuche:

int *B = NULL;
int *C = &*B;

Es stellt sich heraus C == NULL, und kein segfault. So &*B dereferenziert nicht wirklich B bevor er seine Adresse nimmt.

Meine Vermutung ist, dass der Präprozessor Instanzen von entfernt &* und *& bevor sie überhaupt zum Compiler gelangen, da sie sich gegenseitig negieren, aber ich kann keine Dokumentation finden, um zu überprüfen, ob dies Standard ist C oder Compiler-spezifisch.

Strippt der Präprozessor &* und *&und kann ich dieses Verhalten von einem bestimmten Compiler erwarten?

  • Der Compiler könnte diese Anweisung optimieren, aber ich bezweifle, dass der Präprozessor dies tun würde.

    – Annäherung an DarknessFish

    21. Januar 2014 um 1:22 Uhr

  • Es wird vom Vorprozessor nicht “gestrippt”. Es ist der Compiler selbst, der das erkennt &* ist ein no-op.

    – Heiße Licks

    21. Januar 2014 um 1:25 Uhr

  • Dies ist ein undefiniertes Verhalten. Der Optimierer hat Ihren Code zufällig so verarbeitet, dass nichts Katastrophales passiert ist, aber der Computer kann segfaulten, später ausfallen oder Dämonen aus Ihrer Nase fliegen lassen.

    – Benutzer2357112

    21. Januar 2014 um 7:27 Uhr

  • Der Präprozessor entfernt es besser nicht: int *p, *q; int foo = *p & *q; – vollkommen legaler Code, aber nur der Compiler kann erkennen, dass es sich um den binären Operator handelt.

    – MSalter

    21. Januar 2014 um 8:33 Uhr

  • Es ist viel darüber gesagt worden &* jetzt. Aber du fragst auch danach *&was trivial, weil ungefährlich ist: if & ist erlaubt, es ist sicher, es wieder zu dereferenzieren, machen *& auch ein Noop. Da bei diesem Vorgang aber nichts passieren kann, bedarf es keiner besonderen Behandlung.

    – glglgl

    21. Januar 2014 um 9:28 Uhr

Benutzer-Avatar
Shafik Yaghmur

Dies wird nicht vom Vorprozessor entfernt, &* am Ende nur dem Zeiger selbst entspricht, wir können dies sehen, indem wir zu gehen Entwurf des C99-Standards 6.5.3.2 Adress- und Umleitungsoperatoren Absatz 4 was sagt:

Der unäre *-Operator bezeichnet die Indirektion. Wenn der Operand auf eine Funktion zeigt, ist das Ergebnis ein Funktionsbezeichner; Wenn es auf ein Objekt zeigt, ist das Ergebnis ein lvalue, der das Objekt bezeichnet. Wenn der Operand vom Typ „Zeiger auf Typ“ ist, hat das Ergebnis den Typ „Typ“. Wenn dem Zeiger ein ungültiger Wert zugewiesen wurde, ist das Verhalten des unären *-Operators undefiniert.87)

und Fußnote 87 sagt:

Somit ist &*E äquivalent zu E (auch wenn E ein Nullzeiger ist),[…]

und Absatz 3 sagt (Betonung von mir):

Der unäre &-Operator liefert die Adresse seines Operanden. Wenn der Operand vom Typ ”Typ” ist, hat das Ergebnis den Typ ”Zeiger auf Typ”. Wenn der Operand das Ergebnis eines unären *-Operators ist, wird weder dieser Operator noch der &-Operator ausgewertet und das Ergebnis ist so, als ob beide weggelassen würdenaußer dass die Einschränkungen für die Operatoren weiterhin gelten und das Ergebnis kein Lvalue ist.

Aktualisieren

Es lohnt sich wahrscheinlich, das zu beachten gcc und clang Sie können die Ergebnisse der Vorverarbeitung anzeigen, indem Sie verwenden -E Flagge(live sehen) und in Visual Studio /EP(live sehen).

Erwähnenswert ist auch, dass MSalters in seinem Kommentar sagte, dass er nur die beiden Token hat &* reicht nicht aus, um den Zusammenhang zu verstehen, wie sein Beispiel zeigt:

int *p, *q ;
int foo = *p & *q ;

Also einfach entfernen &* nicht einmal während der Vorverarbeitung möglich, da Ihnen nicht genügend Informationen zur Verfügung stünden, um festzustellen, ob & war das Adresse von Betreiber bzw bitweise und Operator.

  • Ich denke das beantwortet meine Frage. Die Antwort ist nein, es wird nicht entfernt: Der Compiler selbst betrachtet es als äquivalent zum Zeiger. Da es im Standard ist, können wir erwarten, dass das Verhalten über Compiler hinweg konsistent ist.

    – evenex_code

    21. Januar 2014 um 1:24 Uhr

  • @evenex_code es sollte über Compiler hinweg konsistent sein und wenn nicht, müsste es dokumentiert werden.

    – Shafik Yaghmour

    21. Januar 2014 um 1:25 Uhr

  • @Shafik Irgendeine Idee, ob dies auch für den C ++ 11-Standard gilt. Es würde diese noch unbeantwortete Frage beantworten, die ich gepostet habe. Posten Sie eine Antwort, in der Sie dies zitieren, und zeigen Sie, dass dies auch für C ++ 11 gilt, und Sie haben +25 Wiederholungen 🙂

    – Prätorianer

    21. Januar 2014 um 1:26 Uhr


  • Denken Sie daran, dass der Compiler nicht weiß, wann er auswertet *Bob es ein l-Wert oder ein r-Wertalso wird davon ausgegangen l-Wert bis das Gegenteil bewiesen ist und den Wert von B zurückgibt (ohne Dereferenzierung). Und die & Operator angewendet auf ein l-Wert gibt einfach die Adresse zurück, die durch dargestellt wird l-Wert (als ein r-Wert).

    – Heiße Licks

    21. Januar 2014 um 1:29 Uhr


  • @Praetorian, soweit ich weiß, trifft es nicht zu C++11ich werde mich bei Gelegenheit damit beschäftigen.

    – Shafik Yaghmour

    21. Januar 2014 um 3:07 Uhr

Benutzer-Avatar
Eric Postpischil

Der Präprozessor wird nicht ausgeblendet &*. Der C 2011-Standard sagt jedoch in 6.5.3.2 3, ungefähr &:

Wenn der Operand [of &] ist das Ergebnis eines unären * Operator, weder dieser Operator noch der & Operator wird ausgewertet und das Ergebnis ist so, als ob beide weggelassen würden, außer dass die Einschränkungen für die Operatoren weiterhin gelten und das Ergebnis kein L-Wert ist.

Wie von den oben erwähnten Beschränkungen gefordert, ist der Operand von * muss Zeigertyp haben. Daher, &*3 wird nicht geändert 3 durch diese Klausel; es verstößt gegen die Beschränkungen, weil 3 hat keinen Zeigertyp. Zusätzlich, &*x nicht ganz geändert x, da das Ergebnis kein Lvalue ist. Nicht erlaubt sind beispielsweise:

int a, *x;
x   = &a; // Normal, allowed.
&*x = &a; // Not allowed; `&*x` does not became exactly the same as `x`. 

1350260cookie-checkEntfernt der C-Präprozessor Instanzen von “&*”?

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

Privacy policy