Como void * a = & a é legal?


88

Considere o seguinte código C ++:

void* a = &a;

Por que o compilador não reclama por usar um identificador não declarado?

Além disso, o que o compilador considera ser a variável a? É um ponteiro para um objeto vazio ou é um ponteiro para um void*ponteiro?




15
Deve mencionar porque você deseja fazer isso - para obter um ponteiro para o topo da pilha (a partir do qual você pode mexer em todos os tipos de coisas).
OrangeDog

Respostas:


95

O escopo da declaração de variáveis ​​em C ++ pode ser bastante surpreendente:

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

Portanto, &aé void**mas, uma vez que qualquer tipo de ponteiro é implicitamente conversível em void*...


Como eu atribuiria um objeto útil a isso?
user2681063

22
@ user2681063 a = &userfulObject?
Nikos C.

4
@MarkGarcia: Observe que void *a = a;seria UB se declarado localmente, caso contrário, está bem no escopo do namespace.
Nawaz

1
@TheodorosChatzigiannakis: Eu acredito que sim.
Matthieu M.

1
Uma citação específica seria muito bom aqui.
Benjamin Gruenbaum

30

É equivalente a

void* a;
a = &a;

Portanto, afoi declarado. Portanto, aobtém o endereço de aescrito em a. Portanto, é um ponteiro para um ponteiro vazio. (Você não definiu nenhum objeto ainda.)


9
Tecnicamente, você definiu um objeto. aem si é um objeto. (Nem todos os objetos têm tipos definidos pelo usuário em C ++)
MSalters

1
@MSalters, de que 'objeto' você fala? : D
Gusdor

3
@Gusdor Só podemos assumir o que está além do vazio do horizonte de eventos.
Cole Johnson de

Eles são chamados de maneiras diferentes, no entanto, o "efeito" é o mesmo neste caso
Stasik de

Eles não são equivalentes em geral, mas neste cenário são.
Lightness Races in Orbit de

7

Em void* a, aé declarado como um ponteiro não para um voidtipo, mas para "qualquer" tipo (caso especial). Um endereço (posição na memória) é atribuído aa , como a qualquer outra variável sendo declarada, é claro.

Depois disso, a expressão &aé avaliada para inicializar a variável (também a, mas isso não é relevante) recém-declarada. O tipo de &aé "ponteiro para ponteiro para qualquer tipo", que é um caso especial de "ponteiro para qualquer tipo", totalmente compatível com o tipo dea . Portanto, nenhuma mensagem do compilador.

Corolário: não use void*se desejar uma verificação de tipo forte. Qualquer coisa pode ser convertida para ele. Exatamente o oposto na direção reversa, exceto paravoid* si mesmo (seria uma exceção desnecessária que um tipo fosse incompatível com ele mesmo).

Além disso, AFAIR isso realmente vem de C.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.