c++ - ¿Por qué std:: bitset sugiere más bits disponibles de lo que sizeof dice que hay?
unsigned (2)
Estoy trabajando en algunos problemas simples de manipulación de bits en C ++, y encontré esto mientras intentaba visualizar mis pasos. Entiendo que el número de bits asignados a diferentes tipos primitivos puede variar de un sistema a otro. Para mi máquina, sizeof(int)
genera 4
, así que tengo 4 caracteres de bits para mi valor. Ahora también sé que la definición de un byte suele ser de 8 bits, pero no es necesariamente el caso. Cuando salgo CHAR_BIT
obtengo 8
. Por lo tanto, espero que haya un total de 32 bits para mis valores int
.
Entonces puedo seguir adelante e imprimir el valor binario de mi int
en la pantalla:
int max=~0; //All my bits are turned on now
std::cout<<std::bitset<sizeof(int)*CHAR_BIT>(max)<<std::endl;
$:11111111111111111111111111111111
Puedo aumentar el tamaño del conjunto de bits si quiero sin embargo:
int max=~0;
std::cout<<std::bitset<sizeof(int)*CHAR_BIT*3>(max)<<std::endl;
$:000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111
¿Por qué hay tantos? Hubiera esperado tener solo 32 unidades, rellenadas con ceros. En su lugar, hay el doble, ¿qué está pasando?
Cuando repito el experimento con unsigned int
, que tiene el mismo tamaño que int
, los adicionales no aparecen:
unsigned int unmax=~0;
std::cout<<std::bitset<sizeof(unsigned int)*CHAR_BIT*3>(unmax)<<std::endl;
$:000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111
Cuando escribes int max=~0;
, el max
será de 32 bits rellenados con 1s, que interpretado como entero es -1
.
Cuando escribes
std::bitset<sizeof(int)*CHAR_BIT>(max)
// basically, same as
std::bitset<32>(-1)
std::bitset
tener en cuenta que el constructor std::bitset
toma un unsigned long long
. Por lo tanto, el -1
que le pasas se convierte a una representación de 64 bits de -1
, que se rellena con 1 de 64 bits (porque tienes un valor negativo, la extensión de signo lo mantiene como tal, rellenando los 32 bits más a la izquierda). con 1s).
Por lo tanto, el constructor de std::bitset
obtiene un unsigned long long
completo con 1s, e inicializa los 32 bits que pidió con 1s. Entonces, cuando lo imprimes, obtienes:
11111111111111111111111111111111
Luego, cuando escribes:
std::bitset<sizeof(int)*CHAR_BIT*3>(max)
// basically, same as
std::bitset<96>(-1)
El constructor std::bitset
inicializará 64 bits más a la derecha de los 96 que pidió con el valor del unsigned long long
que pasó, por lo que esos 64 bits se rellenan con 1s. Los bits restantes (32 a la izquierda) se inicializan con ceros. Así que cuando lo imprimes, obtienes:
000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111
Por otro lado, cuando escribe unsigned int unmax=~0;
, estás asignando todos los 1s a un unsigned int
, por lo que obtienes UINT_MAX
.
Luego, cuando escribes:
std::bitset<sizeof(unsigned int)*CHAR_BIT*3>(unmax)
// basically, same as
std::bitset<96>(UINT_MAX)
El UINT_MAX
que pasa, se convierte a una representación de 64 bits, que es 32 bits más a la derecha rellenados con 1s y el resto de todos los 0s (porque tiene un valor positivo, la extensión de signo lo mantiene como tal, al rellenar los 32 bits más a la izquierda con 0s ).
Así que el unsinged long long
que obtiene el constructor std::bitset
se representa como 32 0s, seguido de 32 1s. Inicializará 64 bits más a la derecha de los 96 que pidió con 32 0s seguidos de 32 1s. Los 32 bits restantes más a la izquierda (de 96) se inicializan con ceros. Así que cuando lo imprimes, obtienes (64 0s seguido de 32 1s):
000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111
El constructor de std::bitset
toma un unsigned long long
, y cuando intenta asignar un -1 (que es lo que ~0
está en un int
) a un unsigned long long
, obtiene 8 bytes (64 bits) por valor de 1s .
No sucede con unsigned int
porque está asignando el valor de 4294967295 en lugar de -1, que es 32 1s en un unsigned long long