C ++: ¿por que bool tiene 8 bits de largo?

132

En C ++, me pregunto por qué el tipo bool tiene 8 bits de largo (en mi sistema), donde solo un bit es suficiente para mantener el valor booleano.

Solía ​​creer que era por razones de rendimiento, pero luego, en una máquina de 32 bits o 64 bits, donde los registros tienen 32 o 64 bits de ancho, ¿cuál es la ventaja de rendimiento?

¿O es solo una de estas razones "históricas"?

Jérôme
fuente
9
Un bool no es de 8 bits en mi sistema. Son 4 bytes, lo mismo que un int.
Brian Neal
21
la última vez que alguien pensó lo que estás pensando, terminamos con std :: vector <bool>, la "característica" stl más odiada de la historia =)
Viktor Sehr
1
Jldupont, creo que me has leído mal. Estaba pidiendo un sistema, donde sizeof(bool)estaría 4. Podría jurar que msvc tenía bools de 32 bits, pero lo intenté y no es así.
avakar
77
Para ser justos, el problema vector<bool>no es que intente ser inteligente y empaquetar los trozos en bits, sino que intente hacer esto y disfrazarse como un contenedor STL . Un bitset simple hubiera estado bien siempre que no pretenda ser un contenedor STL.
jalf
2
@avakar: puede estar confundiendo el booltipo de datos C ++ con el BOOLtipo de Windows al que está typedefed long. Entonces sizeof(bool) != sizeof(BOOL), lo que estoy seguro causa mucha confusión (y probablemente una buena cantidad de errores). Particularmente porque también hay booleany BOOLEANtypedefs en Windows, que son alias para unsigned char. Además, tenga en cuenta que si bien es común boolque sea de 1 byte, el estándar C ++ tiene una nota que indica específicamente que sizeof(bool)puede ser más grande.
Michael Burr

Respuestas:

219

Porque cada tipo de datos C ++ debe ser direccionable.

¿Cómo crearías un puntero a un solo bit? No puedes Pero puede crear un puntero a un byte. Por lo tanto, un booleano en C ++ suele tener un tamaño de byte. (También puede ser más grande. Eso depende de la implementación. Lo principal es que debe ser direccionable, por lo que ningún tipo de datos C ++ puede ser más pequeño que un byte)

jalf
fuente
77
El direccionamiento de "byte" es una opción arquitectónica (nivel hw): se podría diseñar un sistema con una "unidad de direccionamiento" diferente. Para los procesadores comunes, el direccionamiento de un "byte" de todos modos termina obteniendo más de un "byte" de la memoria externa: esto se debe a razones de eficiencia.
jldupont
8
Sí, es una opción de hardware, y si el hardware lo permite, el tamaño de un bool podría cambiar. Pero el OP preguntó por qué un bool tiene 8 bits de ancho, y en sistemas donde ese es el caso, generalmente es porque la CPU solo puede direccionar bytes de 8 bits.
jalf
2
@jldupont: Hay algunos sistemas en los que las direcciones de los punteros son más finas que los bytes (he programado anteriormente en la TI TMS34010 / 20 anterior, que usa punteros sabios), pero son EXCEPCIONALMENTE raros.
Michael Kohne
1
No estoy seguro de lo que quieres decir. Cada objeto debe ser direccionable, es decir, debe ser posible recuperar la dirección de un objeto. El objeto no tiene que almacenar su propia dirección. Un carácter suele tener 8 bits de ancho, suficiente para almacenar cualquiera de los 256 caracteres, pero cada carácter también tiene una dirección definida por el lugar en el que se encuentra en la memoria. Es por eso que puede crear un puntero a un carácter.
jalf
88
Si puedo aportar una analogía dudosa: hay ocho pisos en mi edificio, pero la oficina de correos no reconoce que son direcciones diferentes. Entonces, si quiero una dirección para mí solo, entonces tengo que alquilar todo el edificio, a pesar de que realmente calzo en un piso. No estoy usando los otros siete pisos para "almacenar una dirección", solo me veo obligado a desperdiciarlos debido a la regla de la Oficina de Correos de que las direcciones se refieren a edificios, no a pisos. Los objetos C ++ deben tener una dirección para sí mismos: no hay salas de correos para ordenar el correo después de la entrega ;-)
Steve Jessop
39

La memoria es byte direccionable. No puede direccionar un solo bit, sin cambiar o enmascarar el byte leído de la memoria. Me imagino que esta es una razón muy grande.

Stephen Roantree
fuente
1
No siempre. El 8051 MCU, por ejemplo, tiene 16 bytes de ubicaciones direccionables de bits
Beached
20

Un booleantipo normalmente sigue a la unidad más pequeña de memoria direccionable de la máquina de destino (es decir, generalmente el byte de 8 bits).

El acceso a la memoria siempre está en "fragmentos" (varias palabras, esto es para la eficiencia a nivel de hardware , transacciones de bus): un bit booleano no se puede abordar "solo" en la mayoría de los sistemas de CPU. Por supuesto, una vez que los datos están contenidos en un registro , a menudo hay instrucciones especializadas para manipular bits de forma independiente.

Por esta razón, es bastante común utilizar técnicas de "empaquetado de bits" para aumentar la eficiencia en el uso de tipos de datos base "booleanos". Una técnica como enum(en C) con potencia de codificación 2 es un buen ejemplo. El mismo tipo de truco se encuentra en la mayoría de los idiomas.

Actualizado : Gracias a una excelente discusión, me llamó la atención que, sizeof(char)==1por definición, en C ++. Por lo tanto, el direccionamiento de un tipo de datos "booleano" está bastante vinculado a la unidad más pequeña de memoria direccionable (refuerza mi punto).

jldupont
fuente
Para todos los comentarios que dejó sobre esto, es impresionante que haya boolomitido la parte más importante de la respuesta: un tipo sigue a la unidad más pequeña de memoria asignable porque C ++ requiere que sea posible crearle punteros . Sin ese requisito, boolposiblemente podría haberse representado como un solo bit, incluso en las máquinas actuales direccionables por bytes.
jalf
1
hmmm ... podría crear una arquitectura de CPU donde un poco podría ser direccionable ... Incluso podría escribir un compilador, etc. para ello. Podría tener una región especial de memoria (o lo que sea) que sería "poco direccionable". No es imposible por ningún tramo de la imaginación.
jldupont
2
Sí, y en ese sistema, un bool podría convertirse en un solo bit. Pero el OP no preguntó "por qué es un bool de 8 bits de ancho en una CPU hipotética jlduponts". Preguntó sobre las CPU actuales, comunes y cotidianas, y en ellas, es porque son direccionables por bytes.
jalf
44
sizeof (char) == 1 por definición en C ++, por lo que lo que su hardware puede o no hacer no es relevante. No puede tener sizeof (bool) <sizeof (char). BTW C ++ se define de tal manera que puede tener un puntero "grueso" para abordar alguna subunidad de lo que el hardware puede abordar si no es conveniente tener la unidad direccionable de hardware más pequeña. Esto se ha utilizado al menos en algunos compiladores de C para arquitecturas direccionables de palabras antiguas.
Programador
@AProgrammer:: sizeof(char)==1 definitionese es el mejor contraargumento de mi argumentación. ¡Gracias!
jldupont
6

Las respuestas acerca de que 8 bits son la menor cantidad de memoria direccionable son correctas. Sin embargo, algunos idiomas pueden usar 1 bit para booleanos, de alguna manera. Me parece recordar que Pascal implementó conjuntos como cadenas de bits. Es decir, para el siguiente conjunto:

{1, 2, 5, 7}

Puede que tenga esto en la memoria:

01100101

Puede, por supuesto, hacer algo similar en C / C ++ si lo desea. (Si realiza un seguimiento de un montón de booleanos, podría tener sentido, pero realmente depende de la situación).

Benjamin Oakes
fuente
8
De hecho, C ++ hace esto con el vector contenedor especializado <bool>, comúnmente se considera un desastre.
C ++ también hace esto con "campos de bits", heredados de C. Al declarar una variable miembro de una estructura / clase, puede declarar el número de bits utilizados para almacenar el valor (por ejemplo, "campo corto sin signo: 3").
@Neil: ¿por qué se ve comúnmente como un desastre? ¿Es un problema de rendimiento?
Jérôme
2
@ Jerome: es porque, dado que un bit no es direccionable, no puede comportarse de la manera habitual vector. En realidad no es un contenedor de tipo STL, porque hay restricciones en el comportamiento. Lo peor es que causa problemas con alguien que tiene boolsy quiere hacer uno vectorde ellos. Es un comportamiento sorprendente, y eso no es lo que quieres en un idioma.
David Thornley
1
@jldupont: es suficiente hacer un punto como este una vez. Y C ++ no garantiza que los bits sean direccionables (más bien lo contrario), sin importar de lo que sea capaz el hardware.
1

Sé que esto es viejo, pero pensé en tirar mis 2 centavos.

Si limita su tipo booleano o de datos a un bit, su aplicación corre el riesgo de sufrir daños en la memoria. ¿Cómo maneja las estadísticas de error en la memoria que solo tiene un bit de largo?

Fui a una entrevista de trabajo y una de las declaraciones que el líder del programa me dijo fue: "Cuando enviamos la señal para lanzar un misil, simplemente enviamos un bit de encendido a apagado por vía inalámbrica. Enviar un bit es extremadamente rápido y nosotros Necesito que esa señal sea lo más rápida posible ".

Bueno, fue una prueba para ver si entendía los conceptos y bits, bytes y manejo de errores. Qué fácil sería para un chico malo enviar un mensaje de un bit. O qué sucede si durante la transmisión el bit se voltea hacia el otro lado.

Cire
fuente
Haga una nueva pregunta , no publique su pregunta como respuesta a otras preguntas.
Igor Jerosimić
66
Creo que la pregunta contenida en esta "respuesta" es en realidad retórica, es decir, la razón por la que no implementamos booleanos como un bit es porque un solo bit no puede manejar las estadísticas de error.
Stephen Holt
1
@StephenHolt pero esa no es la razón y TBH esta respuesta no tiene ningún sentido.
doc
1
...¿qué? No sé a qué te refieres con "estadísticas de error", ya sean CRC o similares, o representaciones de trampa. Pero, en cualquier caso, incluso los tipos más grandes no usan sus bits 'sobrantes' adicionales para "estadísticas de error" ya que todos los codificadores, excepto los de entornos extremos, asumen con razón que su hardware puede manejar la detección / corrección de errores antes de que su código lea la memoria, por lo que No es necesario que dediquen su tiempo a rellenar cada variable con información de verificación o lo que sea. Esa no es la razón por la que boolusa 8 bits en la máquina de OP y 32 en la mía, ya que esos otros 7 o 31 bits ciertamente no se usan para ninguna "estadística de error". Esto no tiene sentido
underscore_d
1

Algunos compiladores incrustados tienen un tipo int1 que se utiliza para empaquetar bits de banderas booleanas (por ejemplo, la serie CCS de compiladores C para MPU de Microchip). Establecer, borrar y probar estas variables utiliza instrucciones de nivel de bit de una sola instrucción, pero el compilador no permitirá otras operaciones (por ejemplo, tomar la dirección de la variable), por los motivos que se indican en otras respuestas.

EBlake
fuente