O que é CHAR_BIT?


91

Citar o código para calcular o valor absoluto inteiro (abs) sem desviar de http://graphics.stanford.edu/~seander/bithacks.html :

int v;           // we want to find the absolute value of v
unsigned int r;  // the result goes here 
int const mask = v >> sizeof(int) * CHAR_BIT - 1;

r = (v + mask) ^ mask;

Variação patenteada:

r = (v ^ mask) - mask;

O que é CHAR_BITe como usar?

Respostas:


-2

Você deve estar ciente de que este código depende do comportamento definido pela implementação de bitshift direito em tipos assinados. O gcc promete sempre dar o comportamento são (extensão de bit de sinal), mas ISO C permite que a implementação preencha com zeros os bits superiores.

Uma maneira de contornar este problema:

#ifdef HAVE_SIGN_EXTENDING_BITSHIFT
int const mask = v >> sizeof(int) * CHAR_BIT - 1;
#else
int const mask = -((unsigned)v >> sizeof(int) * CHAR_BIT - 1);
#endif

Seu Makefileou config.hetc. podem definir HAVE_SIGN_EXTENDING_BITSHIFTno momento da construção dependendo da sua plataforma.


120
Não entendo como essa resposta pode ser aceita, já que não responde à pergunta, embora seja um comentário muito interessante.
qdii

14
@Mauris: Alguém editou a pergunta e promoveu uma subquestão ao título da pergunta. O título original era reconhecidamente horrível, mas a pergunta do OP era sobre como o código de hack do bit citado funciona, e "não funciona, pelo menos não portável e aqui está o porquê" é uma resposta útil.
R .. GitHub PARAR DE AJUDAR O GELO

12
Ah, eu entendi. Infelizmente, essa pergunta aparece muito alto nos resultados da Pesquisa Google para "O que é CHAR_BIT?" , mesmo que essa não fosse a pergunta original. :( Dada a sua explicação, entendo por que você escreveu esta resposta, mas para a posteridade pode ser mais útil (a) remover sua resposta e reescrevê-la como um comentário para a pergunta, de modo que @AaraK apareça no topo, ou (b) edite sua resposta para que responda ao título atual da pergunta.
Lynn

1
Devido à diferença de intenção (ões) entre a pergunta original do OP e a interpretação do editor, parece que a natureza da solicitação original foi involuntariamente alterada. Embora ambas as questões (original e editada) tenham mérito, essa discrepância precisa ser tratada. Eu agora pergunto: Esta resposta pode ser adicionada a um wiki? Isso possivelmente ajudaria as pessoas que estão procurando por esse tipo de informação, embora não seja pertinente à pergunta original. Depois disso, a questão poderia ser editada novamente, para se adequar ao pedido original de dato datuashvili. Apenas um leitor preocupado ...

2
Acabei de olhar para o histórico desta questão e a questão original não pergunta em lugar nenhum como o código funciona. A pergunta que o editor promoveu ao título é a única pergunta real ali.
plugwash de

224

CHAR_BITé o número de bits em char. Atualmente, quase todas as arquiteturas usam 8 bits por byte, mas nem sempre é o caso. Algumas máquinas mais antigas costumavam ter bytes de 7 bits.

Ele pode ser encontrado em <limits.h>.


3
Alguns DSPs têm 10 ou mais bytes de bits.
Juri Robl

63
C requer CHAR_BIT>=8e permite valores muito maiores para DSPs que têm apenas um único tamanho de tipo, geralmente 32 bits. POSIX requer CHAR_BIT==8. Em geral, você pode assumir qualquer arquitetura orientada para servidor multiusuário / multitarefa ou orientada para uso interativo com qualquer chance de estar conectado à Internet ou de intercambiar dados textuais com o mundo externo CHAR_BIT==8.
R .. GitHub PARAR DE AJUDAR ICE

6
@caf: Não, é que o C99 requer que os tipos int8_te uint8_texistam. Portanto, existe um tipo de largura 8. Uma vez que sizeofqualquer tipo deve ser compatível com, sizeof charna verdade sizeof int8_tdeve ser 1. Portanto CHAR_BIT == 8. Escrevi algo sobre essa obeservação aqui: gustedt.wordpress.com/2010/06/01/how-many-bits-has-a-byte
Jens Gustedt

22
@Jens Gustedt: Por favor, cite uma seção nas especificações C99. Dos tipos inteiros de largura exata, a especificação C99 diz "Esses tipos são opcionais." (7.18.1.1/3) Os tipos de largura mínima e largura mais rápida são obrigatórios, no entanto.
Jamesdlin

3
@jamesdlin & caf: desculpe, eu confundi as coisas. sim, o requisito a que me referi vem, na verdade, do POSIX para stdint.h. Portanto, é necessário, e também é marcado como extensão do padrão ISO C , sem se referir a uma versão particular desse padrão. Foi mal.
Jens Gustedt

2

Tentar responder à pergunta explícita (o que é CHAR_BIT) e à pergunta implícita (como isso funciona) na pergunta original.


Um caractere em C e C ++ representa a menor unidade de memória que o programa C pode endereçar *

CHAR_BIT em C e C ++ representa o número de bits em um caractere. Deve ser sempre pelo menos 8 devido a outros requisitos do tipo char. Na prática, em todos os computadores modernos de uso geral é exatamente 8, mas alguns sistemas históricos ou especializados podem ter valores mais altos.

Java não tem equivalente a CHAR_BIT ou sizeof, não há necessidade disso, pois todos os tipos primitivos em Java têm tamanho fixo e a estrutura interna dos objetos é opaca para o programador. Se traduzir este código para Java, você pode simplesmente substituir "sizeof (int) * CHAR_BIT - 1" pelo valor fixo 31.

Neste código específico, ele está sendo usado para calcular o número de bits em um int. Esteja ciente de que esse cálculo pressupõe que o tipo int não contém bits de preenchimento.

Supondo que seu compilador escolha estender o sinal em deslocamentos de bits de números com sinal e supondo que seu sistema use a representação de complemento de 2s para números negativos, isso significa que "MASK" será 0 para um valor positivo ou zero e -1 para um valor negativo.

Para negar um número de complemento de dois, precisamos executar um não bit a bit e depois adicionar um. Podemos igualmente subtrair um e negá-lo aos bits.

Novamente, assumindo que a representação de complemento de dois -1 é representada por todos os uns, então exclusivo ou com -1 é equivalente à negação bit a bit.

Portanto, quando v é zero, o número é deixado sozinho; quando v é um, ele é negado.

Algo para se estar ciente é que o estouro assinado em C e C ++ é um comportamento indefinido. Portanto, usar esta implementação do ABS no valor mais negativo leva a um comportamento indefinido. Isso pode ser corrigido adicionando-se casts de forma que a linha final do programa seja avaliada em unsigned int.

* Que geralmente é, mas não necessariamente a mesma, que a menor unidade de memória que o hardware pode endereçar. Uma implementação pode potencialmente combinar várias unidades de memória endereçável por hardware em uma unidade de memória endereçável por programa ou dividir uma unidade de memória endereçável por hardware em várias unidades de memória endereçável por programa.

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.