Почему std :: bitset предлагает больше доступных бит, чем sizeof говорит, что есть?

Я работаю над некоторыми проблемами с небольшими манипуляциями в C++ и сталкивался с этим, пытаясь визуализировать мои шаги. Я понимаю, что количество бит, присвоенных различным примитивным типам, может варьироваться от системы к системе. Для моей машины sizeof(int) выводит 4, поэтому у меня есть 4 char бит для моей стоимости. Я также знаю теперь, что определение байта обычно составляет 8 бит, но это не обязательно так. Когда я CHAR_BIT я получаю 8. Поэтому я ожидаю, что для моих значений int будет в общей сложности 32 бита.

Затем я могу продолжить и напечатать двоичное значение моего int на экране:

int max=~0; //All my bits are turned on now
std::cout<<std::bitset<sizeof(int)*CHAR_BIT>(max)<<std::endl;

$:11111111111111111111111111111111

Я могу увеличить размер бита, если хочу:

int max=~0;
std::cout<<std::bitset<sizeof(int)*CHAR_BIT*3>(max)<<std::endl;

$:000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111

Почему их так много? Я ожидал, что у меня будет всего 32, с нулями. Вместо этого в два раза больше, что происходит?

Когда я повторяю эксперимент с unsigned int, который имеет тот же размер, что и int, лишние не появляются:

unsigned int unmax=~0;
std::cout<<std::bitset<sizeof(unsigned int)*CHAR_BIT*3>(unmax)<<std::endl;

$:000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111

Ответ 1

Конструктор std::bitset принимает unsigned long long, и когда вы пытаетесь назначить -1 (что равно ~0 в int) для unsigned long long, вы получаете 8 байт (64 бит) стоимости 1s.

Это не происходит с unsigned int потому что вы назначаете значение 4294967295 вместо -1, которое равно 32 1 с unsigned long long

Ответ 2

Когда вы пишете int max=~0; , max будет 32 бита, заполненного 1s, который интерпретируется как integer -1.

Когда вы пишете

std::bitset<sizeof(int)*CHAR_BIT>(max)
// basically, same as
std::bitset<32>(-1)

Вы должны иметь в виду, что конструктор std::bitset принимает unsigned long long. Таким образом, -1 который вы передаете ему, преобразуется в 64-битное представление -1, которое содержит 64 бита, заполненных 1 (поскольку у вас есть отрицательное значение, расширение знака поддерживает его как таковое, заполняя 32 левые бит с 1 сек.).

Поэтому конструктор std::bitset получает unsigned long long заполненный 1s, и инициализирует 32 бита, которые вы задали с помощью 1s. Итак, когда вы печатаете его, вы получаете:

11111111111111111111111111111111

Затем, когда вы пишете:

std::bitset<sizeof(int)*CHAR_BIT*3>(max)
// basically, same as
std::bitset<96>(-1)

Конструктор std::bitset инициализирует 64 самых правых бита 96, которые вы задали, с unsigned long long которую вы передали, поэтому эти 64 бита заполнены 1s. Остальные биты (32 слева) инициализируются нулями. Поэтому, когда вы печатаете его, вы получаете:

000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111

С другой стороны, когда вы пишете unsigned int unmax=~0; , вы назначаете все 1s unsigned int, так что вы получаете UINT_MAX.

Затем, когда вы пишете:

std::bitset<sizeof(unsigned int)*CHAR_BIT*3>(unmax)
// basically, same as
std::bitset<96>(UINT_MAX)

UINT_MAX который вы передаете, преобразуется в 64-битное представление, которое представляет собой 32 самых правых бита, заполненных 1 и оставшихся всех 0 (поскольку у вас есть положительное значение, расширение знака поддерживает его как таковое, заполняя 32 крайних левых бита 0).

Таким образом, unsinged long long который получает конструктор std::bitset, представлен как 32 0s, за которым следуют 32 1s. Он будет инициализировать 64 самых правых бита из 96, которые вы задали с 32 0, за которыми следуют 32 1. Остальные 32 левых бита (из 96) инициализируются нулями. Поэтому, когда вы печатаете его, вы получаете (64 0 с 32-ю):

000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111