Por que um tamanho booleano de 1 byte e não 1 bit?

127

Em C ++,

  • Por que um tamanho booleano de 1 byte e não 1 bit?
  • Por que não existem tipos como números inteiros de 4 ou 2 bits?

Estou perdendo as coisas acima ao escrever um emulador para uma CPU

Asm
fonte
10
No C ++, você pode "empacotar" os dados usando campos de bits. struct Packed { unsigned int flag1 : 1; unsigned int flag2: 1; };. A maioria dos compiladores alocará um total unsigned int, no entanto, eles lidam com a manipulação de bits quando você lê / escreve. Também eles lidam sozinhos com as operações do módulo. Isso é um unsigned small : 4atributo tem um valor entre 0 e 15, e quando deve chegar a 16, não vai substituir o bit anterior :)
Matthieu M.

Respostas:

208

Porque a CPU não pode endereçar nada menor que um byte.

Paul Tomblin
fonte
10
Droga, agora que é estranho Sir
Asm
31
Na verdade, os quatro x86 instruções bt, bts, btre btc pode enfrentar o bit individual!
Fredoverflow
11
Eu acho que btendereça um deslocamento de byte e, em seguida, testa o bit em um determinado deslocamento, independentemente, ao especificar um endereço que você digita em bytes ... os literais de deslocamento de bit ficariam um pouco prolixo (desculpe o trocadilho).
precisa saber é o seguinte
2
@ seis: Você pode carregar o início de uma matriz em um registro e, em seguida, o "bit offset" relativo em um segundo. O deslocamento do bit não está limitado a "dentro de um byte", pode ser qualquer número de 32 bits.
Fredoverflow
4
Bem, sim e não. Nós temos campos de bits e poderíamos ter um ponteiro de campo de bits, que é endereço + número de bit. Obviamente, esse ponteiro não seria convertível em void * devido ao requisito de armazenamento extra para o número de bits.
Maxim Egorushkin
32

Da Wikipedia :

Historicamente, um byte era o número de bits usado para codificar um único caractere de texto em um computador e, por esse motivo, é o elemento endereçável básico em muitas arquiteturas de computadores.

Então, byte é a unidade endereçável básica , abaixo da qual a arquitetura do computador não pode ser endereçada. E como (provavelmente) não existem computadores que suportam byte de 4 bits, você não tem 4 bits, bool etc.

No entanto, se você pode projetar uma arquitetura que possa endereçar 4 bits como unidade endereçável básica, terá booltamanho 4 bits, apenas nesse computador!

Nawaz
fonte
4
"você terá tamanho int de 4 bits, apenas nesse computador" - não, não, porque o padrão proíbe CHAR_BIT de ser menor que 8. Se a unidade endereçável na arquitetura for menor que 8 bits, então um A implementação do C ++ precisará apenas apresentar um modelo de memória diferente do modelo de memória do hardware subjacente.
21711 Steve Jobs (
@ Steve: oops ... eu ignorei isso. Removido inte chardo meu post.
Nawaz
1
você também não pode ter um de 4 bits bool, porque charé a menor unidade endereçável em C ++ , independentemente do que a arquitetura possa endereçar com seus próprios opcodes. sizeof(bool)deve ter um valor de pelo menos 1 e os boolobjetos adjacentes devem ter seus próprios endereços em C ++ , portanto, a implementação precisa apenas torná-los maiores e desperdiçar memória. É por isso que os campos de bits existem como um caso especial: os membros do campo de bits de uma estrutura não precisam ser endereçáveis ​​separadamente, portanto podem ser menores que a char(embora a estrutura inteira ainda não possa ser).
9788 Steve Jobs -
@ Steve Jessop: isso parece interessante. você poderia me dar a referência da especificação da linguagem onde diz que charé a menor unidade endereçável em C ++?
Nawaz
3
a instrução específica mais próxima é provavelmente 3.9 / 4: "A representação do objeto de um objeto do tipo T é a sequência de N objetos de caracteres não assinados, capturados pelo objeto do tipo T, onde N é igual a sizeof (T)". Obviamente, sizeof(bool)não pode ser 0,5 :-) Suponho que uma implementação possa fornecer legalmente ponteiros de sub-bytes como uma extensão, mas objetos "comuns" como bool, alocados de maneiras comuns, precisam fazer o que o padrão diz.
9788 Steve Jobs,
12

A resposta mais fácil é; é porque a CPU endereça a memória em bytes e não em bits, e as operações bit a bit são muito lentas.

No entanto, é possível usar a alocação de tamanho de bit em C ++. Existe a especialização std :: vector para vetores de bits e também estruturas que recebem entradas de tamanho de bits.

sukru
fonte
1
Não tenho certeza se eu concordaria que as operações bit a bit são lentas. ands, nots, xors etc são muito rápidos. Geralmente, a implementação das operações bit a bit é lenta. No nível da máquina, eles são bastante rápidos. Ramificação ... agora isso é lento.
Hogan
3
Apenas para deixar mais claro, se você criar um vetor de booleanos e colocar 24 booleanos nele, serão necessários apenas 3 bytes (3 * 8). Se você inserir outro booleano, será necessário outro byte. No entanto, se você empurrar outra boolean, não vai tomar quaisquer bytes extras porque ele usa os bits "livres" no último byte
Pedro Loureiro
sim, eu também duvido operações bitewise são lentos :)
Pedro Loureiro
Os vetores de bits não criam alocações de tamanho de bit. eles criam alocações do tamanho de bytes. Não é possível alocar um único bit.
John Dibling
1
A leitura de um único bit em um vetor de bit requer três operações: shift e, e outro turno novamente. Escrever é dois. Considerando que bytes individuais podem ser acessados ​​com um único.
Sukru
7

Nos velhos tempos, quando eu tinha que ir para a escola em uma nevasca furiosa, subindo os dois lados, e o almoço era qualquer animal que pudéssemos rastrear na floresta atrás da escola e matar com as próprias mãos, os computadores tinham muito menos memória disponível do que hoje. O primeiro computador que usei tinha 6K de RAM. Não 6 megabytes, não 6 gigabytes, 6 kilobytes. Nesse ambiente, fazia muito sentido agrupar o maior número possível de booleanos em um int e, portanto, usamos regularmente as operações para removê-los e colocá-los.

Hoje, quando as pessoas zombam de você por ter apenas 1 GB de RAM, e o único lugar em que você pode encontrar um disco rígido com menos de 200 GB é em uma loja de antiguidades, não vale a pena arrumar os bits.

Jay
fonte
Exceto quando se lida com bandeiras. Coisas como Definir várias opções em algo ... por exemplo. 00000001 + 00000100 = 00000101.
Armstrongest
@ Atomix: Eu quase nunca faço mais isso. Se eu precisar de dois sinalizadores, crio dois campos booleanos. Eu costumava escrever código onde empacotava sinalizadores assim e depois escrevia "if flags & 0x110! = 0 then" ou algo parecido, mas isso é enigmático e hoje em dia geralmente faço campos separados e escrevo "if fooFlag || barFlag " em vez de. Eu não descartaria a possibilidade de casos em que empacotar bandeiras como essa é melhor por algum motivo, mas não é mais necessário salvar a memória como costumava ser.
Jay
2
Na verdade, é bastante vale o seu problema para embalar pedaços, se você quiser que o seu cálculo para ser rápido - em que grande quantidade de dados que você armazena na memória. Empacotar booleanos não é apenas para armazenamento menor - significa que você pode ler suas matrizes de entradas booleanas 8 vezes mais rápido (em termos de largura de banda) do que quando elas são descompactadas, e isso geralmente é bastante significativo. Além disso, você pode usar operações de bits, como popc (contagem de população), que acelera seu trabalho na própria CPU.
Einpoklum 18/05
2
Um número verdadeiramente grande de booleanos é o que você trabalha todos os dias: DBMSes, aprendizado de máquina, simulações científicas e várias outras coisas. E - apenas trabalhar nelas significa copiá-las - da memória para o cache. Um milhão de bools não é nada, pense bilhões.
Einpoklum 18/05
1
@PeterCordes Sim, com certeza, se eu tivesse um conjunto de booleanos que eram logicamente a "mesma idéia", de modo que eu naturalmente os considerasse uma "matriz" em algum sentido, e se eu vou mascará-los ou filtrá-los ou caso contrário, execute operações bit a bit nelas, empacotá-las em bytes poderá fazer sentido. Como eu disse anteriormente, tenho dificuldade em pensar na última vez em que trabalhei em um aplicativo em que essas condições se aplicavam, mas você dá alguns bons exemplos, e tenho certeza que com um pouco de imaginação poderíamos pensar nos outros.
Jay
6

Você pode ter bools de 1 bit e ints de 4 e 2 bits. Mas isso criaria um conjunto de instruções estranho, sem ganho de desempenho, porque é uma maneira não natural de olhar para a arquitetura. Na verdade, faz sentido "desperdiçar" uma parte melhor de um byte, em vez de tentar recuperar esses dados não utilizados.

O único aplicativo que se preocupa em compactar vários bools em um único byte, na minha experiência, é o Sql Server.

Paul Sasik
fonte
5

Você pode usar campos de bits para obter números inteiros de tamanho inferior.

struct X
{
    int   val:4;   // 4 bit int.
};

Embora seja geralmente usado para mapear estruturas para exatos padrões de bits esperados por hardware:

struct SomThing   // 1 byte value (on a system where 8 bits is a byte
{
    int   p1:4;   // 4 bit field
    int   p2:3;   // 3 bit field
    int   p3:1;   // 1 bit
};
Martin York
fonte
5

Porque um byte é a menor unidade endereçável do idioma.

Mas você pode fazer o bool demorar 1 bit, por exemplo, se você tiver um monte deles, por exemplo. em uma estrutura, assim:

struct A
{
  bool a:1, b:1, c:1, d:1, e:1;
};
bratao
fonte
2

boolpode ter um byte - o menor tamanho endereçável da CPU ou pode ser maior. Não é incomum ter boolque ter esse tamanho intpara fins de desempenho. Se, para fins específicos (por exemplo, simulação de hardware), você precisar de um tipo com N bits, poderá encontrar uma biblioteca para isso (por exemplo, a biblioteca GBL tem BitSet<N>classe). Se você está preocupado com o tamanho de bool(você provavelmente tem um contêiner grande), pode embalar os bits por conta própria ou usá- std::vector<bool>lo para fazer isso por você (tenha cuidado com o último, pois ele não atende aos requisitos do contêiner).

Gene Bushuyev
fonte
2

Pense em como você implementaria isso no nível do emulador ...

bool a[10] = {false};

bool &rbool = a[3];
bool *pbool = a + 3;

assert(pbool == &rbool);
rbool = true;
assert(*pbool);
*pbool = false;
assert(!rbool);
franji1
fonte
2

Porque, em geral, a CPU aloca memória com 1 byte como unidade básica, embora algumas CPUs como MIPS usem uma palavra de 4 bytes.

No entanto, vectortrata de boolmaneira especial, com vector<bool>um bit para cada bool é alocado.

Ryan Li
fonte
1
Acredito que até o processador MIPS lhe dará acesso a um byte individual, embora exista uma penalidade de desempenho.
Paul Tomblin
@ Paul: Sim, você está certo, mas geralmente as palavras específicas lw/ swsão muito mais amplamente usadas.
Ryan Li
Não conhece o MIPS, mas a arquitetura IA-64 permite apenas o acesso no limite de 64 bits.
Gene Bushuyev 7/01
0

O byte é a unidade menor de armazenamento de dados digitais de um computador. Em um computador, a RAM possui milhões de bytes e qualquer um deles possui um endereço. Se ele tivesse um endereço para cada bit, um computador poderia gerenciar 8 vezes menos RAM do que aquilo que pode.

Mais informações: Wikipedia

Francesco Pasa
fonte
0

Mesmo quando o tamanho mínimo possível é 1 Byte, você pode ter 8 bits de informações booleanas em 1 Byte:

http://en.wikipedia.org/wiki/Bit_array

A linguagem Julia possui o BitArray, por exemplo, e eu li sobre implementações em C ++.

Diego Javier Zea
fonte