Pergunta

No Visual Studio C ++ versão 9 (e provavelmente outras versões também), o seguinte código:

int a = sizeof(void);
void const *b = static_cast<void const *>("hello world");
b += 6;

estes erros :

error C2070: 'void': illegal sizeof operand
error C2036: 'const void *' : unknown size

Esse código funciona sob GCC, que trata sizeof(void) como 1 .

Existe alguma maneira de contornar esta limitação, como lançar explicitamente char * para fins de aritmética de ponteiro aumenta a confusão (void * é bem reconhecido e usado como um ponteiro typeless a memória bruta).

Update0

  • Por favor, note, eu estou bem ciente do existência da norma.
  • Eu quero para fazer ponteiro bruto aritmética.
  • Eu tomo sizeof(void) para mostrar que eu estou bem ciente do fato que não é 1 é o causa do problema.
  • O código exemplo é simplesmente para demonstrar que é necessária para gerar os erros.
  • Eu sei que isso não é uma maneira "normal" a utilização void, mas este é C, e essas coisas acontecem.
  • Sim, as pessoas precisam fazer isso em baixo nível. Eu não estou atrás porque, eu sou depois como. Se você quer saber por que, dê uma olhada em algumas fontes do kernel, ou o seu glibc amigável.

Update1

Parece que esta questão tem gerado uma grande confusão. A questão não é sobre por ter sizeof(void) == 1 não é padrão, mas o que fazer quando não é.

Na instância que ponteiro de byte único aritmética é para ser feito, verifica-se que a projeção para char * é a resposta correta, não porque *(void *) não tem tamanho, mas porque o padrão de fato garante que *(char *) é sempre 1. Portanto, o uso de char * é sempre correto e congruente com void * com a extensão GCC para efeitos da aritmética ponteiro bruto.

Para reforçar ainda mais o ponto, void * é a escolha correta para ponteiros para memória typeless e char * é o tipo correto de elenco para para ponteiro bruto aritmética .

Foi útil?

Solução 8

Parece é para uso char * para aritmética de ponteiro, porque sizeof(char) é sempre definido como 1, e para ser da melhor granularidade endereçável em qualquer plataforma.

Assim, em breve, não há maneira de contornar a limitação, char * é de fato a maneira correta de fazê-lo.

Matthias Wandel teve a resposta certa mas com uma justificação diferente.

Outras dicas

Incrementar um ponteiro é tecnicamente suposto incrementá-lo por qualquer tamanho de coisa que seu apontando. pontos vazios em nada, de modo que o tamanho é desconhecida.

É uma minúcia para alguns compiladores para deixá-lo incrementar ponteiros void.

A carcaça é chato, porque você tem que quer lançá-lo para outro ponteiro, e depois de volta, ou fazer algo embaraçoso como (*(char *)&voidptr) += 6

Pessoalmente, eu tinha acabado de declará-lo como um char * para fins de aritmética

Em C sizeof linguagem não pode ser aplicada aos tipos incompletos. void é um tipo incompleto, razão pela qual você não pode usá-lo como operando de sizeof.

Ponteiro aritmética dos ponteiros void * também não é suportado, a fim C. para ser utilizado com a aritmética do ponteiro do ponteiro tem de ponto de tipo de objecto, que não é void.

GCC permite tanto como uma extensão da linguagem estranha.

void * é para implicar "ponteiro para desconhecido"

A adição de 6 a um ponteiro nulo é, portanto, indefinido, porque você está pedindo o compilador para avançar o ponteiro, "do tamanho de 6 objetos desconhecidos".

Você não deveria estar fazendo isso.

Há duas perguntas diferentes aqui. O primeiro é para void, e o segundo para void*. Eles são de diferentes tipos, e têm pouco em comum ao lado do nome.

void é usado principalmente para declarações de funções / definições (como o tipo de retorno ou para significar "não tem argumentos"). Você nunca pode, eventualmente, ter um objeto do tipo void. Sempre. Portanto, é difícil ver a necessidade de descobrir o tamanho do objeto inexistente. comportamento do GCC não é padrão, e uma extensão intencional . No entanto, eu acredito que eles escolheram sizeof(void) == 1 porque o C ++ padrão exige que cada objeto para levar pelo menos um byte de espaço.

meios void* "ponteiro para dados reais, mas sem as informações de tipo relevante." É perfeitamente possível ter void*; e você vai correr para eles, muito. No entanto, porque o tipo de informação é ignorado você não pode manipular o ponteiro muito. Isso ocorre por design, porque se você não sabe o que você tem que você realmente não sabe o que você pode fazer com ele.

Mas se você quiser tratar a memória como uma coleção de bytes, em seguida, char* faz isso. A char é um byte, em todos os lugares. Uma série de bytes é um char*. Se você encontrar este estranho, byte* uso (onde você define byte como algo como unsigned char).

Eu posso ver o erro na primeira linha, pelo menos - você tem sizeof (void) e deve ser sizeof (void *), nenhum

Para puramente apontando para dados brutos e incrementando esse ponteiro pelo número de bytes de um bloco de dados ocupa, eu sempre uso char *. Eu, então, reformular o ponteiro para um ponteiro estrutura de dados relevantes, uma vez que preciso tratá-la como algo específico. Incrementando a void * não é portável entre compiladores.

void * é bem reconhecido e usado como um ponteiro typeless à memória matéria.

Correto. Não ter um meio de tipo não tendo um tamanho de qualquer um.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top