Dlaczego void * a = & a jest legalny?

88

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?

user2681063
źródło
6
Punkt deklaracji
Grijesh Chauhan
15
Powinienem wspomnieć, dlaczego chcesz to zrobić - aby uzyskać wskaźnik na szczyt stosu (z którego możesz bawić się różnymi rzeczami).
OrangeDog,

Odpowiedzi:

95

Zakres deklaracji zmiennych w C ++ może być dość zaskakujący:

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

Dlatego &ajest, void**ale ponieważ każdy typ wskaźnika jest niejawnie konwertowany na void*...

Matthieu M.
źródło
Jak przypisać do tego przydatny obiekt?
user2681063
22
@ user2681063 a = &userfulObject?
Nikos C.,
4
@MarkGarcia: Zauważ, że void *a = a;byłoby to UB, gdyby zostało zadeklarowane lokalnie, w przeciwnym razie jest w porządku w zakresie przestrzeni nazw.
Nawaz
1
@TheodorosChatzigiannakis: Myślę, że tak.
Matthieu M.,
1
Przydałaby się tutaj specyfikacja.
Benjamin Gruenbaum
30

Jest odpowiednikiem

void* a;
a = &a;

Dlatego azostał ogłoszony. Więc adostaje adres awpisany a. Jest to więc wskaźnik do pustego wskaźnika. (Nie zdefiniowałeś jeszcze żadnych obiektów).

Stasik
źródło
9
Technicznie rzecz biorąc, zdefiniowałeś jeden obiekt. asama w sobie jest przedmiotem. (Nie wszystkie obiekty mają typy zdefiniowane przez użytkownika w C ++)
MSalters
1
@MSalters o czym jest ten „obiekt”, o którym mówisz? : D
Gusdor
3
@Gusdor Możemy tylko założyć, co znajduje się poza pustką horyzontu zdarzeń.
Cole Johnson,
Nazywa się je inaczej, jednak „efekt” jest taki sam w tym przypadku
Stasik
Na ogół nie są równoważne, ale w tym scenariuszu są.
Wyścigi lekkości na orbicie
7

W void* a, ajest zadeklarowany jako wskaźnik nie do voidtypu, ale do typu „dowolnego” (przypadek specjalny). Adres (pozycja w pamięci) jest przypisany a, tak jak każdej innej deklarowanej zmiennej, oczywiście.

Następnie wyrażenie &ajest oceniane w celu zainicjowania zmiennej (również a, ale nie ma to znaczenia) właśnie zadeklarowanej. Typ &ato „wskaźnik do wskaźnika do dowolnego typu”, co jest specjalnym przypadkiem „wskaźnika do dowolnego typu”, w pełni zgodnym z typem a. 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ątkiem void*siebie samego (byłby to niepotrzebny wyjątek, że typ byłby ze sobą niezgodny).

AFAIR to naprawdę pochodzi od C.

Mario Rossi
źródło