Pergunta

Como pode um portably executar a aritmética de ponteiros com precisão byte único?

Tenha em mente que:

  • char não é 1 byte em todas as plataformas
  • sizeof(void) == 1 só está disponível como uma extensão no GCC
  • Enquanto algumas plataformas podem ter ponteiro deref restrições de alinhamento ponteiro, aritmética pode ainda exigir uma granularidade mais fina do que o tamanho do menor tipo POD fundamentais
Foi útil?

Solução

Seu pressuposto é falho -. sizeof(char) é definido para ser 1 em todos os lugares

A partir da C99 padrão (TC3) , na seção 6.5.3.4 ( "O operador sizeof"):

(parágrafo 2)

O operador sizeof produz o tamanho (Em bytes) do seu operando, o qual pode ser uma expressão ou o nome entre parênteses de um tipo.

(parágrafo 3)

Quando aplicado a um operando que tem tipo char não assinado carvão animal, ou assinado char, (ou uma versão qualificada do mesmo) o resultado é 1.

Quando estes são tomados em conjunto, torna-se claro que em C, qualquer que seja o tamanho de um char é, que o tamanho é um "byte" (mesmo que seja mais de 8 bits, em alguma determinada plataforma).

A char é, portanto, o menor tipo endereçável. Se você precisa resolver em unidades menores do que um char, sua única opção é para ler um char de cada vez e uso bit a bit operadores para mascarar as partes do char que você deseja.

Outras dicas

sizeof(char) sempre retorna 1, em C e C ++ . A char é sempre um byte.

De acordo com o char padrão é o menor pedaço endereçável de dados. Você simplesmente não pode endereço com maior precisão -. Você precisa fazer as malas / descompactar manualmente

sizeof(char) é garantido para ser 1 pelo padrão C. Mesmo se char usa 9 bits ou mais.

Assim que você pode fazer:

type *pt;
unsigned char *pc = (unsigned char *)pt;

E o uso pc para a aritmética. Atribuindo pc para pt utilizando o molde acima é comportamento indefinido pela norma C embora.

Se char é mais do que 8-bits de largura, você não pode fazer byte de precisão aritmética de ponteiro no portátil (ANSI / ISO) C. Aqui, pela byte , quero dizer 8 bits. Isso ocorre porque o próprio tipo fundamental é maior do que 8 bits.

converter o ponteiro a um uintptr_t. Este será um inteiro sem sinal que é do tamanho de um ponteiro. Agora faça a sua aritmética sobre ele, em seguida, lançar a volta resultado para um ponteiro do tipo que você deseja excluir a referência.

(Note que intptr_t é assinado, o que geralmente não é o que você quer! É mais seguro ficar com uintptr_t menos que você tenha uma boa razão para não!)

Eu não entendo o que você está tentando dizer com sizeof(void) sendo 1 em GCC. Enquanto tipo char pode teoricamente consistir em mais de 1 byte máquina subjacente, em linguagem C sizeof(char) é 1 e sempre exatamente 1. Em outras palavras, do ponto de vista da linguagem C, char é sempre 1 "byte" (C-byte, não byte máquina). Depois de entender isso, você também iria entender que sizeof(void) sendo 1 em GCC não ajudá-lo de qualquer forma. Em GCC a aritmética de ponteiro em ponteiros void * funciona exatamente da mesma forma que a aritmética de ponteiro em ponteiros char *, o que significa que, se em algum char * plataforma não funciona para você, então void * não vai funcionar para você também.

Se em alguma plataforma objetos char consistir em vários bytes da máquina, a única maneira de acessar unidades menores de memória do que um objeto char completa seria a utilização de operações bit a bit para "extrair" e "modificar" as partes necessárias de um char completa objeto. linguagem C não oferece nenhuma maneira de diretamente endereço de qualquer coisa menor que char. Mais uma vez char é sempre um C-byte.

O padrão C99 define o uint8_t que é um byte. Se o compilador não suporta este tipo, você poderia defini-lo usando um typedef. Claro que você precisa de uma definição diferente, dependendo da plataforma e / ou compilador. tudo o pacote em um arquivo de cabeçalho e usá-lo em todos os lugares.

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