In che modo void * a = & a è legale?


88

Considera il seguente codice C ++:

void* a = &a;

Perché il compilatore non si lamenta per l'utilizzo di un identificatore non dichiarato?

Inoltre, cosa considera il compilatore la variabile a? È un puntatore a un oggetto vuoto o è un puntatore a un void*puntatore?




15
Dovresti menzionare il motivo per cui vorresti farlo: per ottenere un puntatore in cima allo stack (da cui puoi giocherellare con ogni sorta di cose).
OrangeDog

Risposte:


95

Lo scopo della dichiarazione delle variabili in C ++ può essere piuttosto sorprendente:

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

Pertanto, &aè void**ma poiché qualsiasi tipo di puntatore è convertibile implicitamente in void*...


Come assegnerei a questo un oggetto utile?
user2681063

22
@ user2681063 a = &userfulObject?
Nikos C.

4
@MarkGarcia: nota che void *a = a;sarebbe UB se dichiarato localmente, altrimenti va bene nell'ambito dello spazio dei nomi.
Nawaz

1
@ TheodorosChatzigiannakis: credo che lo sia, sì.
Matthieu M.

1
Una citazione specifica sarebbe davvero carina qui.
Benjamin Gruenbaum

30

È equivalente a

void* a;
a = &a;

Pertanto, aè stato dichiarato. Quindi aottiene l'indirizzo di ascritto in a. Quindi è un puntatore a un puntatore vuoto. (Non hai ancora definito alcun oggetto.)


9
Tecnicamente, hai definito un oggetto. aessa stessa è un oggetto. (Non tutti gli oggetti hanno tipi definiti dall'utente in C ++)
MSalters

1
@MSalters, cos'è questo "oggetto" di cui parli? : D
Gusdor

3
@Gusdor Possiamo solo supporre ciò che si trova oltre il vuoto dell'orizzonte degli eventi.
Cole Johnson

Sono chiamati in modo diverso, tuttavia l '"effetto" è lo stesso in questo caso
Stasik

Non sono equivalenti in generale, ma in questo scenario lo sono.
Gare di leggerezza in orbita

7

In void* a, aviene dichiarato come un puntatore non a un voidtipo ma a un tipo "qualsiasi" (caso speciale). Un indirizzo (posizione in memoria) viene assegnato a, come a qualsiasi altra variabile dichiarata, ovviamente.

Dopodiché, l'espressione &aviene valutata per inizializzare la variabile (anche a, ma questo non è rilevante) appena dichiarata. Il tipo di &aè "puntatore a puntatore a qualsiasi tipo", che è un caso speciale di "puntatore a qualsiasi tipo", pienamente compatibile con il tipo di a. Ergo, nessun messaggio del compilatore.

Corollario: non utilizzare void*se si desidera un controllo del tipo forte. Tutto può essere convertito in esso. Esattamente l'opposto nella direzione opposta, tranne che per void*se stesso (sarebbe un'eccezione non necessaria che un tipo fosse incompatibile con se stesso).

Inoltre, AFAIR questo viene davvero da C.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.