C ++: por que bool tem 8 bits?

132

Em C ++, estou me perguntando por que o tipo bool tem 8 bits de comprimento (no meu sistema), onde apenas um bit é suficiente para armazenar o valor booleano?

Eu costumava acreditar que era por motivos de desempenho, mas em uma máquina de 32 bits ou 64 bits, onde os registros têm 32 ou 64 bits de largura, qual é a vantagem de desempenho?

Ou é apenas uma dessas razões "históricas"?

Jérôme
fonte
9
Um bool não tem 8 bits no meu sistema. É 4 bytes, o mesmo que um int.
Brian Neal
21
última vez que alguém pensou que você está pensando, acabamos com std :: vector <bool>, o "recurso" já =) stl mais odiado
Viktor Sehr
1
No entanto, acho que você me interpretou mal. Eu estava pedindo um sistema, onde sizeof(bool)seria 4. Eu poderia jurar que o msvc tinha bools de 32 bits, mas tentei e não.
avakar
7
Para ser justo, o problema vector<bool>não é que ele tenta ser inteligente e empacota bools em bits, mas que tenta fazer isso e se disfarçar como um contêiner STL . Um conjunto de bits simples ficaria bem desde que também não pretendesse ser um contêiner STL.
jalf
2
@avakar - você pode estar confundindo o booltipo de dados C ++ com o BOOLtipo do Windows ao qual é digitado o tipo long. Então sizeof(bool) != sizeof(BOOL), o que tenho certeza causa muita confusão (e provavelmente um bom número de bugs). Especialmente porque também existem booleane BOOLEANtypedefs no Windows, que são aliases para unsigned char. Além disso, observe que, embora seja comum boolter 1 byte, o padrão C ++ possui uma observação que indica especificamente que sizeof(bool)pode ser maior.
Michael Burr

Respostas:

219

Porque todo tipo de dados C ++ deve ser endereçável.

Como você criaria um ponteiro para um único bit? Você não pode. Mas você pode criar um ponteiro para um byte. Portanto, um booleano em C ++ geralmente é do tamanho de bytes. (Também pode ser maior. Depende da implementação. O principal é que ele deve ser endereçável, para que nenhum tipo de dados C ++ possa ser menor que um byte)

jalf
fonte
7
O endereçamento "byte" é uma opção arquitetural (nível hw): é possível projetar um sistema com uma "unidade de endereçamento" diferente. Para processadores comuns, endereçar um "byte" de qualquer maneira acaba buscando mais do que um "byte" da memória externa: isso se deve a razões de eficiência.
precisa saber é o seguinte
8
Sim, é uma escolha de hardware e, se o hardware permitir, o tamanho de um bool pode mudar. Mas o OP perguntou por que um bool tem 8 bits de largura e, em sistemas onde é esse o caso, geralmente é porque a CPU é capaz de endereçar apenas bytes de 8 bits.
jalf
2
@ jldupont: Existem alguns sistemas em que os endereços dos ponteiros são mais granulados que os bytes (eu já havia programado na antiga TI TMS34010 / 20, que usa ponteiros bit a bit), mas eles são extremamente raros.
Michael Kohne
1
Não tenho certeza do que você quer dizer. Todo objeto deve ser endereçável, ou seja, deve ser possível recuperar o endereço de um objeto. O objeto não precisa armazenar seu próprio endereço. Um caractere geralmente tem 8 bits de largura, o suficiente para armazenar 256 caracteres, mas cada caractere também possui um endereço definido por onde está localizado na memória. É por isso que você pode criar um ponteiro para um caractere.
jalf
88
Se posso contribuir com uma analogia desonesta: há oito andares no meu prédio, mas os Correios não reconhecem que são endereços diferentes. Então, se eu quero um endereço só para mim, tenho que alugar o prédio inteiro, mesmo que eu realmente caia no mesmo andar. Não estou usando os outros sete andares para "armazenar um endereço", sou forçado a desperdiçá-los por causa da regra da agência postal que os endereços se referem a edifícios, não a andares. Objetos C ++ devem ter um endereço para si mesmos - sem salas de correios para classificar o correio após a entrega ;-) #
3160 Steve
39

A memória é endereçável em bytes. Você não pode endereçar um único bit, sem mudar ou mascarar a leitura de bytes da memória. Eu imagino que essa seja uma razão muito grande.

Stephen Roantree
fonte
1
Nem sempre. O 8051 MCU, por exemplo, tem 16 bytes de locais endereçáveis bit
encalhada
20

Um booleantipo normalmente segue a menor unidade de memória endereçável da máquina de destino (ou seja, geralmente o byte de 8 bits).

O acesso à memória está sempre em "partes" (várias palavras, isto é para eficiência no nível do hardware , transações de barramento): um bit booleano não pode ser endereçado "sozinho" na maioria dos sistemas de CPU. Obviamente, uma vez que os dados estão contidos em um registro , muitas vezes há instruções especializadas para manipular os bits independentemente.

Por esse motivo, é bastante comum usar técnicas de "empacotamento de bits" para aumentar a eficiência no uso de tipos de dados base "booleanos". Uma técnica como enum(em C) com potência de 2 códigos é um bom exemplo. O mesmo tipo de truque é encontrado na maioria dos idiomas.

Atualizado : graças a uma excelente discussão, foi trazido à minha atenção que, sizeof(char)==1por definição, em C ++. Portanto, o endereçamento de um tipo de dados "booleano" está bastante vinculado à menor unidade de memória endereçável (reforça meu argumento).

jldupont
fonte
Por todos os comentários que você deixou sobre isso, é impressionante que você tenha deixado de fora a parte mais importante da resposta: Um booltipo segue a menor unidade de memória alocável porque o C ++ exige que seja possível criar ponteiros para ele . Sem esse requisito, um boolpoderia ter sido representado como um bit único, mesmo em máquinas atuais endereçáveis ​​por bytes.
jalf
1
hmmm ... Eu poderia criar uma arquitetura de CPU onde um pouco pudesse ser endereçável ... Eu poderia até escrever um compilador etc. Eu poderia ter uma região especial de memória (ou qualquer outra coisa) que seria "pouco endereçável". Não é impossível por nenhuma extensão da imaginação.
precisa saber é o seguinte
2
Sim, e nesse sistema, um bool pode ser feito para ser um bit único. Mas o OP não perguntou "por que um booleano de 8 bits de largura na CPU hipotética do jlduponts"? Ele perguntou sobre as CPUs atuais, comuns e comuns, e sobre essas, é porque elas são endereçáveis ​​por bytes.
jalf
4
sizeof (char) == 1 por definição em C ++, portanto, o que seu hardware pode ou não fazer não é relevante. Você não pode ter sizeof (bool) <sizeof (char). O BTW C ++ é definido de tal maneira que você pode ter um ponteiro "gordo" para endereçar alguma subunidade do que o hardware pode endereçar se não for conveniente ter char a menor unidade endereçável de hardware. Isso foi usado pelo menos em alguns compiladores C para arquiteturas endereçáveis ​​de palavras antigas.
APROGRAMADOR
@ AProgrammer:: sizeof(char)==1 definitionesse é o melhor contra-argumento para a minha argumentação. Obrigado!
precisa saber é o seguinte
6

As respostas sobre 8 bits sendo a menor quantidade de memória endereçável estão corretas. No entanto, alguns idiomas podem usar 1 bit para booleanos, de certa forma. Eu me lembro do Pascal implementando conjuntos como cadeias de bits. Ou seja, para o seguinte conjunto:

{1, 2, 5, 7}

Você pode ter isso na memória:

01100101

Obviamente, você pode fazer algo semelhante em C / C ++, se quiser. (Se você está acompanhando um monte de booleanos, isso pode fazer sentido, mas realmente depende da situação.)

Benjamin Oakes
fonte
8
De fato, o C ++ faz isso com o vetor de contêiner especializado <bool> - geralmente é visto como um desastre.
O C ++ também faz isso com "campos de bits", herdados de C. Ao declarar uma variável de membro de uma estrutura / classe, você pode declarar o número de bits usados ​​para armazenar o valor (por exemplo, "campo curto não assinado: 3").
@ Neil: por que é comumente visto como um desastre? É um problema de desempenho?
Jérôme
2
@ Jerome: É porque, uma vez que um pouco não é endereçável, ele não pode se comportar da maneira regular vector. Na verdade, não é um contêiner do tipo STL, porque há restrições no comportamento. O pior é que isso causa problemas com alguém que tem se boole quer fazer um vectordeles. É um comportamento surpreendente, e não é isso que você deseja em um idioma.
David Thornley
1
@ jldupont - é suficiente fazer uma observação como esta uma vez. E o C ++ não garante que os bits sejam endereçáveis ​​(pelo contrário, o inverso), não importa o que o hardware seja capaz.
1

Eu sei que isso é velho, mas eu pensei em jogar meus 2 centavos.

Se você limitar seu tipo booleano ou de dados a um bit, seu aplicativo estará em risco de interrupção da memória. Como você lida com estatísticas de erro na memória de apenas um bit?

Fui a uma entrevista de emprego e uma das declarações que o líder do programa me disse foi: "Quando enviamos o sinal para lançar um míssil, enviamos apenas um bit on off off via wireless. O envio de um bit é extremamente rápido e nós precisa que esse sinal seja o mais rápido possível ".

Bem, foi um teste para ver se eu entendi os conceitos e bits, bytes e manipulação de erros. Quão fácil seria para um bandido enviar uma mensagem de um bit. Ou o que acontece se durante a transmissão o bit for invertido para o outro lado.

Cire
fonte
Faça uma nova pergunta , não a poste como resposta a outras perguntas.
Igor Jerosimić 14/02
6
Eu acho que a pergunta contida nesta "resposta" é realmente retórica, ou seja, a razão pela qual não implementamos booleanos como um bit é porque um único bit não pode lidar com estatísticas de erro.
Stephen Holt
1
@ StephenHolt, mas não é esse o motivo e TBH, essa resposta não faz sentido.
doc
1
...o que? Não sei o que você quer dizer com "estatísticas de erro", sejam CRCs ou similares ou representações de trap. Mas, em qualquer caso, mesmo os tipos maiores não usam seus bits extras e "sobressalentes" para "estatísticas de erro", pois todos, exceto os codificadores de ambientes extremos, assumem com razão que seu hardware pode lidar com a detecção / correção de erros antes que seu código leia a memória; não precisa gastar seu tempo preenchendo todas as variáveis ​​com informações de verificação ou o que for. Não é por isso que boolusa 8 bits na máquina do OP e 32 na minha, pois os outros 7 ou 31 bits certamente não são usados ​​para nenhuma "estatística de erro". Isso não faz sentido
underscore_d
1

Alguns compiladores incorporados possuem um tipo int1 que é usado para compactar bit boolean flags (por exemplo, série CCS de compiladores C para MPUs de Microchip). A configuração, limpeza e teste dessas variáveis ​​usam instruções de nível de bit de instrução única, mas o compilador não permitirá outras operações (por exemplo, pegar o endereço da variável), pelos motivos mencionados em outras respostas.

EBlake
fonte