En quoi void * a = & a est-il légal?

88

Considérez le code C ++ suivant:

void* a = &a;

Pourquoi le compilateur ne se plaint-il pas d'avoir utilisé un identifiant non déclaré?

De plus, que considère le compilateur comme étant la variable a? Est-ce un pointeur vers un objet vide ou est-ce un pointeur vers un void*pointeur?

user2681063
la source
6
Point de déclaration
Grijesh Chauhan
15
Devrait mentionner pourquoi vous voudriez faire cela - pour obtenir un pointeur vers le haut de la pile (à partir de laquelle vous pouvez jouer avec toutes sortes de choses).
OrangeDog

Réponses:

95

La portée de la déclaration des variables en C ++ peut être assez surprenante:

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

Par conséquent, &aest void**mais puisque tout type de pointeur est implicitement convertible en void*...

Matthieu M.
la source
Comment attribuer un objet utile à cela?
user2681063
22
@ user2681063 a = &userfulObject?
Nikos C.
4
@MarkGarcia: Notez que ce void *a = a;serait UB s'il était déclaré localement, sinon cela convient à la portée de l'espace de noms.
Nawaz
1
@TheodorosChatzigiannakis: Je pense que oui.
Matthieu M.
1
Une citation de spécification serait vraiment bien ici.
Benjamin Gruenbaum
30

C'est équivalent à

void* a;
a = &a;

Par conséquent, aa été déclaré. Obtient donc al'adresse de aécrite a. C'est donc un pointeur vers un pointeur vide. (Vous n'avez encore défini aucun objet.)

Stasik
la source
9
Techniquement, vous avez défini un objet. alui-même est un objet. (Tous les objets n'ont pas de types définis par l'utilisateur en C ++)
MSalters
1
@MSalters De quel «objet» parlez-vous? : D
Gusdor
3
@Gusdor Nous ne pouvons que supposer ce qui se trouve au-delà du vide de l'horizon des événements.
Cole Johnson
Ils sont appelés différemment, mais l '«effet» est le même dans ce cas
Stasik
Ils ne sont pas équivalents en général, mais dans ce scénario, ils le sont.
Courses de légèreté en orbite
7

In void* a, aest déclaré comme un pointeur non pas vers un voidtype mais vers "tout" type (cas particulier). Une adresse (position en mémoire) est affectée à a, comme à toute autre variable déclarée, bien sûr.

Après cela, l'expression &aest évaluée pour initialiser la variable (également a, mais ce n'est pas pertinent) qui vient d'être déclarée. Le type de &aest "pointeur vers un pointeur vers n'importe quel type", ce qui est un cas particulier de "pointeur vers n'importe quel type", entièrement compatible avec le type de a. Ergo, pas de message du compilateur.

Corollaire: ne pas utiliser void*si vous souhaitez une vérification de type forte. Tout peut y être converti. Juste le contraire dans le sens inverse, sauf pour void*lui-même (ce serait une exception inutile qu'un type soit incompatible avec lui-même).

Aussi, AFAIR cela vient vraiment de C.

Mario Rossi
la source