C ++: pourquoi bool fait 8 bits?

132

En C ++, je me demande pourquoi le type booléen a une longueur de 8 bits (sur mon système), où un seul bit suffit pour contenir la valeur booléenne?

J'avais l'habitude de croire que c'était pour des raisons de performances, mais alors sur une machine 32 bits ou 64 bits, où les registres ont une largeur de 32 ou 64 bits, quel est l'avantage des performances?

Ou est-ce juste une de ces raisons «historiques»?

Jérôme
la source
9
Un booléen n'est pas 8 bits sur mon système. C'est 4 octets, la même chose qu'un int.
Brian Neal
21
la dernière fois que quelqu'un a pensé à ce que vous pensez, nous nous sommes retrouvés avec std :: vector <bool>, la "fonctionnalité" stl la plus détestée de tous les temps =)
Viktor Sehr
1
jldupont, je pense que vous m'avez mal lu. Je demandais un système, où sizeof(bool)serait 4. Je pourrais jurer que msvc avait des booléens 32 bits, mais j'ai juste essayé et ce n'est pas le cas.
avakar le
7
Pour être honnête, le problème avec ce vector<bool>n'est pas qu'il essaie d'être intelligent et de regrouper les booléens en bits, mais qu'il essaie de le faire et de se déguiser en conteneur STL . Un ensemble de bits simple aurait été bien tant qu'il ne prétend pas être un conteneur STL.
jalf
2
@avakar - il se peut que vous confondiez le booltype de données C ++ avec le BOOLtype Windows qui est typé à long. Donc sizeof(bool) != sizeof(BOOL), ce qui, j'en suis sûr, cause beaucoup de confusion (et probablement pas mal de bugs). En particulier , car il y a aussi booleanet BOOLEANtypedefs dans Windows, qui sont des alias pour unsigned char. Notez également que s'il est courant boold'être 1 octet, le standard C ++ a une note qui indique spécifiquement que cela sizeof(bool)peut être plus grand.
Michael Burr

Réponses:

219

Parce que chaque type de données C ++ doit être adressable.

Comment créeriez-vous un pointeur vers un seul bit? Vous ne pouvez pas. Mais vous pouvez créer un pointeur vers un octet. Ainsi, un booléen en C ++ est généralement de la taille d'un octet. (Il peut également être plus grand. Cela dépend de l'implémentation. L'essentiel est qu'il soit adressable, donc aucun type de données C ++ ne peut être plus petit qu'un octet)

jalf
la source
7
L'adressage "octet" est un choix architectural (niveau hw): on pourrait très bien concevoir un système avec une "unité d'adressage" différente. Pour les processeurs courants, l'adressage d'un "octet" finit de toute façon par récupérer plus d'un "octet" de la mémoire externe: cela est dû à des raisons d'efficacité.
jldupont
8
Oui, c'est un choix matériel, et si le matériel le permet, la taille d'un booléen pourrait changer. Mais l'OP a demandé pourquoi un booléen avait une largeur de 8 bits, et sur les systèmes où c'est le cas, c'est généralement parce que le CPU n'est capable d'adresser que des octets de 8 bits.
jalf
2
@jldupont: Il y a quelques systèmes où les adresses de pointeurs sont plus fines que les octets (j'ai déjà programmé sur l'ancienne TI TMS34010 / 20, qui utilise des pointeurs bit par bit), mais elles sont EXCÉDEMMENT rares.
Michael Kohne
1
Pas sûr de ce que vous voulez dire. Chaque objet doit être adressable, c'est-à-dire qu'il doit être possible de récupérer l'adresse d'un objet. L'objet n'a pas à stocker sa propre adresse. Un caractère a généralement une largeur de 8 bits, suffisamment pour stocker l'un des 256 caractères, mais chaque caractère a également une adresse définie par l'endroit où il se trouve en mémoire. C'est pourquoi vous pouvez créer un pointeur vers un caractère.
jalf
88
Si je peux apporter une analogie douteuse: il y a huit étages dans mon immeuble, mais la poste ne reconnaît pas que ce sont des adresses différentes. Donc, si je veux une adresse pour moi tout seul, alors je dois louer tout le bâtiment, même si je suis sur un étage. Je n'utilise pas les sept autres étages pour «stocker une adresse», je suis juste obligé de les gaspiller à cause de la règle de la poste qui fait référence aux bâtiments, pas aux étages. Les objets C ++ doivent avoir une adresse pour eux-mêmes - pas de salles de publication pour trier le courrier après la livraison ;-)
Steve Jessop
39

La mémoire est adressable par octets. Vous ne pouvez pas adresser un seul bit, sans décaler ou masquer l'octet lu en mémoire. J'imagine que c'est une très grande raison.

Stephen Roantree
la source
1
Pas toujours. Le MCU 8051, par exemple, a 16 octets d'emplacements adressables par bits
échoué le
20

Un booleantype suit normalement la plus petite unité de mémoire adressable de la machine cible (c'est-à-dire généralement l'octet de 8 bits).

L'accès à la mémoire se fait toujours par "chunks" (multiple de mots, c'est pour l' efficacité au niveau matériel , transactions sur bus): un bit booléen ne peut pas être adressé "seul" dans la plupart des systèmes CPU. Bien entendu, une fois que les données sont contenues dans un registre , il existe souvent des instructions spécialisées pour manipuler les bits indépendamment.

Pour cette raison, il est assez courant d'utiliser des techniques de "bit packing" afin d'augmenter l'efficacité de l'utilisation de types de données de base "booléens". Une technique telle que enum(en C) avec une puissance de codage 2 en est un bon exemple. Le même genre d'astuce se retrouve dans la plupart des langues.

Mise à jour : Grâce à une excellente discussion, il n'a été porté à mon attention que sizeof(char)==1par définition en C ++. Par conséquent, l'adressage d'un type de données "booléen" est assez lié à la plus petite unité de mémoire adressable (renforce mon point).

jldupont
la source
Pour tous les commentaires que vous avez laissés à ce sujet, il est impressionnant que vous boolayez omis la partie la plus importante de la réponse: un type suit la plus petite unité de mémoire allouable car C ++ nécessite qu'il soit possible de créer des pointeurs vers lui . Sans cette exigence, a boolaurait pu être représenté sous la forme d'un seul bit, même sur les machines adressables par octets actuelles.
jalf
1
hmmm ... Je pourrais créer une architecture CPU où un peu pourrait être adressable ... Je pourrais même écrire un compilateur etc. pour cela. Je pourrais avoir une région spéciale de mémoire (ou autre) qui serait "bit adressable". Ce n'est pas du tout impossible à imaginer.
jldupont
2
Oui, et sur ce système, un booléen pourrait être un simple bit. Mais l'OP n'a pas demandé "pourquoi un booléen a une largeur de 8 bits sur un processeur hypothétique jlduponts". Il a posé des questions sur les processeurs courants, courants et quotidiens, et sur ceux-ci, c'est parce qu'ils sont adressables par octets.
jalf
4
sizeof (char) == 1 par définition en C ++, donc ce que votre matériel peut ou ne peut pas faire n'est pas pertinent. Vous ne pouvez pas avoir sizeof (bool) <sizeof (char). BTW C ++ est défini de telle manière que vous pouvez avoir un pointeur "gros" pour adresser une sous-unité de ce que le matériel peut adresser s'il n'est pas pratique d'avoir char la plus petite unité adressable matérielle. Cela a été utilisé au moins dans certains compilateurs C pour les anciennes architectures adressables par mot.
AProgrammer le
@AProgrammer:: sizeof(char)==1 definitionc'est le meilleur contre-argument à mon argumentation. Merci!
jldupont
6

Les réponses sur 8 bits étant la plus petite quantité de mémoire adressable sont correctes. Cependant, certains langages peuvent utiliser 1 bit pour les booléens, d'une certaine manière. Il me semble me souvenir que Pascal implémentait des ensembles sous forme de chaînes de bits. Autrement dit, pour l'ensemble suivant:

{1, 2, 5, 7}

Vous pourriez avoir ceci en mémoire:

01100101

Vous pouvez, bien sûr, faire quelque chose de similaire en C / C ++ si vous le souhaitez. (Si vous suivez un tas de booléens, cela peut avoir du sens, mais cela dépend vraiment de la situation.)

Benjamin Oakes
la source
8
En fait, C ++ le fait avec le vecteur de conteneur spécialisé <bool> - cela est généralement considéré comme un désastre.
C ++ le fait également avec des "champs de bits", hérités de C. Lors de la déclaration d'une variable membre d'une structure / classe, vous pouvez déclarer le nombre de bits utilisés pour stocker la valeur (par exemple, "champ court non signé: 3").
@Neil: pourquoi est-il généralement considéré comme une catastrophe? Est-ce un problème de performances?
Jérôme
2
@Jerome: C'est parce que, comme un bit n'est pas adressable, il ne peut pas se comporter comme un habitué vector. Ce n'est pas en fait un conteneur de type STL, car il y a des contraintes sur le comportement. Ce qui est pire, c'est que cela cause des problèmes à quelqu'un qui a des bools et qui veut en faire un vector. C'est un comportement surprenant, et ce n'est pas ce que vous voulez dans une langue.
David Thornley
1
@jldupont - il suffit de faire un point comme celui-ci une fois. Et C ++ ne garantit pas que les bits sont adressables (plutôt l'inverse), peu importe ce dont le matériel est capable.
1

Je sais que c'est vieux mais je pensais que je mettrais mes 2 cents.

Si vous limitez votre booléen ou votre type de données à un bit, votre application court un risque de curruption de mémoire. Comment gérez-vous les statistiques d'erreur dans la mémoire qui ne fait qu'un bit?

Je suis allé à un entretien d'embauche et l'une des déclarations que m'a dit le responsable du programme était: «Lorsque nous envoyons le signal pour lancer un missile, nous envoyons simplement un bit on off via sans fil. L'envoi d'un bit est extrêmement rapide et nous ont besoin que ce signal soit aussi rapide que possible. "

Eh bien, c'était un test pour voir si je comprenais les concepts et les bits, les octets et la gestion des erreurs. Comment serait-il facile pour un méchant d'envoyer un message d'un bit. Ou que se passe-t-il si, lors de la transmission, le bit est inversé.

Cire
la source
Posez une nouvelle question , ne postez pas votre question comme réponse à d'autres questions.
Igor Jerosimić
6
Je pense que la question contenue dans cette "réponse" est en fait une question rhétorique, c'est-à-dire que la raison pour laquelle nous n'implémentons pas les booléens en un seul bit est qu'un seul bit ne peut pas gérer les statistiques d'erreur.
Stephen Holt
1
@StephenHolt mais ce n'est pas la raison et TBH cette réponse n'a aucun sens.
doc
1
...quelle? Je ne sais pas ce que vous entendez par "statistiques d'erreur", qu'il s'agisse de CRC ou de représentations similaires, ou de représentations de pièges. Mais dans tous les cas, même les plus grands types n'utilisent pas leurs bits supplémentaires 'de réserve' pour les "statistiques d'erreur", car tous les codeurs sauf les environnements extrêmes supposent à juste titre que leur matériel peut gérer la détection / correction d'erreur avant que leur code ne lise la mémoire, donc ils n'ont pas besoin de passer leur temps à remplir chaque variable d'informations de vérification ou autre. Ce n'est pas pourquoi boolutilise 8 bits sur la machine d'OP et 32 ​​sur la mienne, car ces 7 ou 31 bits ne sont certainement pas utilisés pour des "statistiques d'erreur". Cela n'a aucun sens
underscore_d
1

Certains compilateurs embarqués ont un type int1 qui est utilisé pour regrouper les bits des indicateurs booléens (par exemple la série CCS de compilateurs C pour les MPU Microchip). La définition, l'effacement et le test de ces variables utilisent des instructions au niveau du bit à instruction unique, mais le compilateur ne permettra aucune autre opération (par exemple en prenant l'adresse de la variable), pour les raisons indiquées dans d'autres réponses.

EBlake
la source