c++ sizeof unsigned bitset

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