Rozważ następujący kod C ++:
void* a = &a;
Dlaczego kompilator nie skarży się na używanie niezadeklarowanego identyfikatora?
Ponadto, za jaką zmienną uważa kompilator a
? Czy jest to wskaźnik do pustego obiektu, czy też jest to wskaźnik do void*
wskaźnika?
Odpowiedzi:
Zakres deklaracji zmiennych w C ++ może być dość zaskakujący:
void* a = &a; ^~~~~~~~~~~~~~~~~ a declared as `void*` from here on
Dlatego
&a
jest,void**
ale ponieważ każdy typ wskaźnika jest niejawnie konwertowany navoid*
...źródło
a = &userfulObject
?void *a = a;
byłoby to UB, gdyby zostało zadeklarowane lokalnie, w przeciwnym razie jest w porządku w zakresie przestrzeni nazw.Jest odpowiednikiem
void* a; a = &a;
Dlatego
a
został ogłoszony. Więca
dostaje adresa
wpisanya
. Jest to więc wskaźnik do pustego wskaźnika. (Nie zdefiniowałeś jeszcze żadnych obiektów).źródło
a
sama w sobie jest przedmiotem. (Nie wszystkie obiekty mają typy zdefiniowane przez użytkownika w C ++)W
void* a
,a
jest zadeklarowany jako wskaźnik nie dovoid
typu, ale do typu „dowolnego” (przypadek specjalny). Adres (pozycja w pamięci) jest przypisanya
, tak jak każdej innej deklarowanej zmiennej, oczywiście.Następnie wyrażenie
&a
jest oceniane w celu zainicjowania zmiennej (równieża
, ale nie ma to znaczenia) właśnie zadeklarowanej. Typ&a
to „wskaźnik do wskaźnika do dowolnego typu”, co jest specjalnym przypadkiem „wskaźnika do dowolnego typu”, w pełni zgodnym z typema
. Ergo, brak wiadomości kompilatora.Wniosek: nie używaj,
void*
jeśli chcesz silnego sprawdzania typu. Wszystko można na to przekonwertować. Wręcz przeciwnie w odwrotnym kierunku, z wyjątkiemvoid*
siebie samego (byłby to niepotrzebny wyjątek, że typ byłby ze sobą niezgodny).AFAIR to naprawdę pochodzi od C.
źródło