Wie ist void * a = & a legal?

88

Betrachten Sie den folgenden C ++ - Code:

void* a = &a;

Warum beschwert sich der Compiler nicht über die Verwendung eines nicht deklarierten Bezeichners?

Was betrachtet der Compiler als Variable a? Ist es ein Zeiger auf ein nichtiges Objekt oder ein Zeiger auf einen void*Zeiger?

user2681063
quelle
6
Punkt der Erklärung
Grijesh Chauhan
15
Sollte erwähnen, warum Sie dies tun möchten - um einen Zeiger auf die Oberseite des Stapels zu erhalten (von dem aus Sie mit allen möglichen Dingen herumspielen können).
OrangeDog

Antworten:

95

Der Umfang der Deklaration von Variablen in C ++ kann ziemlich überraschend sein:

void* a =               &a;
         ^~~~~~~~~~~~~~~~~
          a declared as `void*` from here on

Daher &aist void**aber da jeder Zeigertyp implizit konvertierbar ist in void*...

Matthieu M.
quelle
Wie würde ich diesem ein nützliches Objekt zuweisen?
user2681063
22
@ user2681063 a = &userfulObject?
Nikos C.
4
@MarkGarcia: Beachten Sie, dass void *a = a;dies UB wäre, wenn es lokal deklariert würde, andernfalls ist es im Namespace-Bereich in Ordnung.
Nawaz
1
@ TheodorosChatzigiannakis: Ich würde es glauben, ja.
Matthieu M.
1
Ein spezielles Zitat wäre hier wirklich schön.
Benjamin Gruenbaum
30

Es ist äquivalent zu

void* a;
a = &a;

Daher awurde erklärt. So abekommt die Adresse von ageschrieben a. Es ist also ein Zeiger auf einen leeren Zeiger. (Sie haben noch keine Objekte definiert.)

Stasik
quelle
9
Technisch haben Sie ein Objekt definiert. aselbst ist ein Objekt. (Nicht alle Objekte haben benutzerdefinierte Typen in C ++)
MSalters
1
@ MSalters von was für einem 'Objekt' sprichst du? : D
Gusdor
3
@Gusdor Wir können nur annehmen, was jenseits der Leere des Ereignishorizonts liegt.
Cole Johnson
Sie werden unterschiedlich genannt, jedoch ist der "Effekt" in diesem Fall der gleiche
Stasik
Sie sind im Allgemeinen nicht gleichwertig, in diesem Szenario jedoch.
Leichtigkeitsrennen im Orbit
7

In void* a, awird als Zeiger nicht zu einem deklarierten voidTyp , sondern „jeden“ Typ (Sonderfall). Eine Adresse (Position im Speicher) wird anatürlich jeder anderen deklarierten Variablen zugewiesen .

Danach wird der Ausdruck &aausgewertet, um die agerade deklarierte Variable (auch , aber dies ist nicht relevant) zu initialisieren . Der Typ von &aist "Zeiger auf Zeiger auf einen beliebigen Typ". Dies ist ein Sonderfall von "Zeiger auf einen beliebigen Typ", der vollständig mit dem Typ von kompatibel ist a. Ergo keine Compiler-Nachricht.

Folgerung: Nicht verwenden, void*wenn Sie eine starke Typprüfung wünschen. Alles kann dazu konvertiert werden. Genau das Gegenteil in umgekehrter Richtung, außer für sich void*selbst (es wäre eine unnötige Ausnahme, dass ein Typ mit sich selbst nicht kompatibel wäre).

Auch AFAIR das kommt wirklich von C.

Mario Rossi
quelle