¿Qué es CHAR_BIT?

91

Citando el código para calcular el valor absoluto entero (abs) sin ramificar 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;

Variación patentada:

r = (v ^ mask) - mask;

¿Qué es CHAR_BITy cómo se usa?

dato datuashvili
fuente

Respuestas:

-1

Debe tener en cuenta que este código depende del comportamiento definido por la implementación del desplazamiento de bits a la derecha en los tipos firmados. gcc promete dar siempre el mismo comportamiento (extensión de bit de signo) pero ISO C permite que la implementación llene con cero los bits superiores.

Una forma de solucionar 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

Su Makefileo config.hetc. pueden definir HAVE_SIGN_EXTENDING_BITSHIFTen el momento de la construcción según su plataforma.

R .. GitHub DEJA DE AYUDAR A ICE
fuente
120
No entiendo cómo esta puede ser una respuesta aceptada ya que no responde la pregunta, aunque es un comentario muy interesante.
qdii
15
@Mauris: Alguien editó la pregunta y promovió una subpregunta al título de la pregunta. El título original era ciertamente horrible, pero la pregunta del OP era sobre cómo funciona el código de pirateo de bits citado, y "no funciona, al menos no de forma portátil, y aquí está el por qué" es una respuesta útil.
R .. GitHub DEJA DE AYUDAR A ICE
12
Ah, ya entiendo. Lamentablemente, esta pregunta aparece muy arriba en los resultados de búsqueda de Google para "¿Qué es CHAR_BIT?" , incluso si esa no era la pregunta original. :( Dada su explicación, entiendo por qué escribió esta respuesta, pero para la posteridad podría ser más útil (a) eliminar su respuesta y reescribirla como un comentario a la pregunta, para que @ AraK aparezca en la parte superior, o (b) edite su respuesta para que responda al título actual de la pregunta.
Lynn
1
Debido a la diferencia en la (s) intención (es) entre la pregunta original del OP y la interpretación del editor de la misma, parece que la naturaleza de la solicitud original se cambió involuntariamente. Si bien ambas preguntas (original y editada) tienen mérito, esta discrepancia debe abordarse. Ahora pregunto: ¿Podría agregarse esta respuesta a un wiki? Esto posiblemente ayudaría a las personas que buscan este tipo de información, aunque no pertenece a la pregunta original. Después de eso, la pregunta podría editarse nuevamente, para ajustarse a la solicitud original de dato datuashvili. Solo un lector preocupado ...
2
Acabo de ver el historial de esta pregunta y la pregunta original en realidad no pregunta en ninguna parte cómo funciona el código. La pregunta que el editor promovió al título es la única pregunta real allí.
Plugwash
224

CHAR_BITes el número de bits en char. En estos días, casi todas las arquitecturas usan 8 bits por byte, pero no siempre es así. Algunas máquinas más antiguas solían tener bytes de 7 bits.

Se puede encontrar en <limits.h>.

AraK
fuente
3
Algunos DSP tienen 10 o más bytes de bits.
Juri Robl
64
C requiere CHAR_BIT>=8y permite valores mucho mayores para los DSP que solo tienen un tamaño de letra único, a menudo de 32 bits. POSIX requiere CHAR_BIT==8. En general, puede asumir cualquier arquitectura multiusuario / multitarea orientada al servidor o orientada al uso interactivo con cualquier posibilidad de estar conectado a Internet o intercambiar datos textuales con el mundo exterior CHAR_BIT==8.
R .. GitHub DEJA DE AYUDAR A ICE
6
@caf: No, es que C99 requiere los tipos int8_ty uint8_tpara existir. Por tanto, existe un tipo de ancho 8. Dado que sizeofcualquier tipo debe ser compatible, en sizeof charrealidad sizeof int8_tdebe ser 1. Entonces CHAR_BIT == 8. He escrito algo sobre esa obeservación aquí: gustedt.wordpress.com/2010/06/01/how-many-bits-has-a-byte
Jens Gustedt
22
@Jens Gustedt: cite una sección de la especificación C99. De los tipos de enteros de ancho exacto, la especificación C99 dice "Estos tipos son opcionales". (7.18.1.1/3) Sin embargo, se requieren los tipos de ancho mínimo y ancho más rápido.
jamesdlin
3
@jamesdlin & caf: lo siento, confundí las cosas. sí, el requisito al que me referí en realidad proviene de POSIX stdint.h. Así que allí se requiere, y también está marcado como Extensión al estándar ISO C , sin hacer referencia a una versión particular de ese estándar. Culpa mía.
Jens Gustedt
2

Tratando de responder tanto la pregunta explícita (qué es CHAR_BIT) como la pregunta implícita (cómo funciona esto) en la pregunta original.


Un carácter en C y C ++ representa la unidad más pequeña de memoria que el programa C puede abordar *

CHAR_BIT en C y C ++ representa el número de bits en un char. Siempre debe ser al menos 8 debido a otros requisitos sobre el tipo de char. En la práctica, en todas las computadoras modernas de propósito general es exactamente 8, pero algunos sistemas históricos o especializados pueden tener valores más altos.

Java no tiene equivalente a CHAR_BIT o sizeof, no es necesario ya que todos los tipos primitivos en Java tienen un tamaño fijo y la estructura interna de los objetos es opaca para el programador. Si traduce este código a Java, simplemente puede reemplazar "sizeof (int) * CHAR_BIT - 1" por el valor fijo 31.

En este código en particular, se utiliza para calcular el número de bits en un int. Tenga en cuenta que este cálculo asume que el tipo int no contiene bits de relleno.

Suponiendo que su compilador elige firmar extender en cambios de bits de números con signo y asumiendo que su sistema usa representación de complemento a 2 para números negativos, esto significa que "MASK" será 0 para un valor positivo o cero y -1 para un valor negativo.

Para negar un número de complemento a dos, debemos realizar un not a nivel de bits y luego agregar uno. De manera equivalente, podemos restar uno y luego negarlo bit a bit.

Nuevamente, asumiendo que la representación del complemento a dos, -1 está representada por todos, por lo que exclusiva o con -1 es equivalente a la negación bit a bit.

Entonces, cuando v es cero, el número se deja solo, cuando v es uno, se niega.

Algo a tener en cuenta es que el desbordamiento firmado en C y C ++ es un comportamiento indefinido. Entonces, el uso de esta implementación de ABS en el valor más negativo conduce a un comportamiento indefinido. Esto se puede solucionar agregando conversiones de modo que la línea final del programa se evalúe en unsigned int.

* Que es generalmente, pero no necesariamente, lo mismo que la unidad más pequeña de memoria que el hardware puede abordar. Una implementación puede potencialmente combinar varias unidades de memoria direccionable por hardware en una unidad de memoria direccionable por programa o dividir una unidad de memoria direccionable por hardware en varias unidades de memoria direccionable por programa.

enchufar
fuente