Me deparei com um pedaço de código void *p = &&abc;
. Qual é o significado &&
disso? Eu sei sobre referências de rvalue, mas acho que &&
usado neste contexto é diferente. O que &&
indica em void *p = &&abc;
?
Me deparei com um pedaço de código void *p = &&abc;
. Qual é o significado &&
disso? Eu sei sobre referências de rvalue, mas acho que &&
usado neste contexto é diferente. O que &&
indica em void *p = &&abc;
?
Respostas:
&&
é a extensão do gcc para obter o endereço do rótulo definido na função atual.
void *p = &&abc
é ilegal em C99 e C ++ padrão.
A compila com g ++.
void*
.
__forceinline
? __declspec(naked)
? Um dos meus MSVCismos favoritos é:, template<typename T> class X { friend T; }
que é inválido C ++ 03.
Esse é o endereço de um rótulo e é um recurso específico do GCC .
int main(void) {
void* startp;
s:
startp = &&s;
printf("the assignment above starts at address %p\n", startp);
return 0;
}
Você poderia ter descoberto sozinho testando:
int main(void) {
void* startp;
int a;
startp = &&a;
printf("startp=%p\n", startp);
return 0;
}
Nesse caso, o GCC diz:
erro: rótulo 'a' usado, mas não definido
Você precisa conhecer o assembler para realmente entender isso, mas tentarei explicar o que significa o endereço de um rótulo.
Depois que o SO carrega o arquivo .exe do disco, um componente do sistema operacional chamado "o carregador" (o Windows tem o "PE Loader", o linux tem o "ELF loader" ou talvez até outros, se estiverem compilados no kernel), ele faz uma "virtualização" desse programa, transformando-o em um processo.
Este processo pensa que é o único na RAM e tem acesso a toda a RAM (ou seja, 0x00000000-0xFFFFFFFF em uma máquina de 32 bits).
(o texto acima é apenas uma breve visão geral do que está acontecendo, você realmente precisa aprender a montagem para entendê-lo totalmente, então tenha paciência comigo)
Agora, o rótulo em um código-fonte é basicamente um endereço. "goto label;" não faz nada mais do que um salto para aquele endereço (pense no ponteiro de instrução no assembly). Esta etiqueta armazena esse endereço de RAM e é assim que você pode descobrir esse endereço.
Depois de aprender ASM, você perceberá que esse endereço aponta para uma instrução dentro da .text
seção do executável. A .text
seção é aquela que contém o código (binário) do programa a ser executado.
Você pode inspecionar isso com:
objdump -x a.out
Conforme descrito no GCC , você pode usar isso para inicializar uma tabela de salto. Alguns geradores de scanner como o re2c (consulte o -g
parâmetro) usam isso para gerar scanners mais compactos. Talvez haja até mesmo um gerador de analisador que utiliza a mesma técnica.