为什么 std::bitset 建议的可用位比 sizeof 说的多?
Why does std::bitset suggest more available bits than sizeof says there are?
我正在用 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
std::bitset
的构造函数采用 unsigned long long
,当您尝试将 -1(这就是 int
中的 ~0
)分配给一个unsigned long long
,你得到 8 个字节(64 位),相当于 1。
unsigned int
不会发生这种情况,因为您分配的值是 4294967295 而不是 -1,后者在 unsigned long long
中是 32 个 1
写成int max=~0;
时,max
就是32位补1,解释成整数就是-1
。
写的时候
std::bitset<sizeof(int)*CHAR_BIT>(max)
// basically, same as
std::bitset<32>(-1)
您需要记住 std::bitset
构造函数采用 unsigned long long
。因此,您传递给它的 -1
被转换为 -1
的 64 位表示形式,即 64 位全部用 1 填充(因为您有一个负值,符号扩展保持它原样,通过用 1 填充最左边的 32 位)。
因此,std::bitset
的构造函数得到一个全为1的unsigned long long
,并将你要求的32位初始化为1。所以,当你打印它时,你会得到:
11111111111111111111111111111111
然后,当你写:
std::bitset<sizeof(int)*CHAR_BIT*3>(max)
// basically, same as
std::bitset<96>(-1)
std::bitset
构造函数将用您传递的 unsigned long long
的值初始化您要求的 96 的最右边的 64 位,因此这 64 位用 1 填充。其余位(最左边的 32 位)用零初始化。所以当你打印它时,你会得到:
000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111
另一方面,当您编写 unsigned int unmax=~0;
时,您会将所有 1 分配给 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(因为您有一个正值,符号扩展保持它原样, 通过用 0 填充最左边的 32 位)。
所以 std::bitset
构造函数得到的 unsinged long long
表示为 32 个 0,然后是 32 个 1。它将用 32 个 0 和后跟 32 个 1 初始化您要求的 96 的最右边的 64 位。剩余的 32 个最左边的位(共 96 个)用零初始化。所以当你打印它时,你会得到(64个0后跟32个1):
000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111
我正在用 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
std::bitset
的构造函数采用 unsigned long long
,当您尝试将 -1(这就是 int
中的 ~0
)分配给一个unsigned long long
,你得到 8 个字节(64 位),相当于 1。
unsigned int
不会发生这种情况,因为您分配的值是 4294967295 而不是 -1,后者在 unsigned long long
写成int max=~0;
时,max
就是32位补1,解释成整数就是-1
。
写的时候
std::bitset<sizeof(int)*CHAR_BIT>(max)
// basically, same as
std::bitset<32>(-1)
您需要记住 std::bitset
构造函数采用 unsigned long long
。因此,您传递给它的 -1
被转换为 -1
的 64 位表示形式,即 64 位全部用 1 填充(因为您有一个负值,符号扩展保持它原样,通过用 1 填充最左边的 32 位)。
因此,std::bitset
的构造函数得到一个全为1的unsigned long long
,并将你要求的32位初始化为1。所以,当你打印它时,你会得到:
11111111111111111111111111111111
然后,当你写:
std::bitset<sizeof(int)*CHAR_BIT*3>(max)
// basically, same as
std::bitset<96>(-1)
std::bitset
构造函数将用您传递的 unsigned long long
的值初始化您要求的 96 的最右边的 64 位,因此这 64 位用 1 填充。其余位(最左边的 32 位)用零初始化。所以当你打印它时,你会得到:
000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111
另一方面,当您编写 unsigned int unmax=~0;
时,您会将所有 1 分配给 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(因为您有一个正值,符号扩展保持它原样, 通过用 0 填充最左边的 32 位)。
所以 std::bitset
构造函数得到的 unsinged long long
表示为 32 个 0,然后是 32 个 1。它将用 32 个 0 和后跟 32 个 1 初始化您要求的 96 的最右边的 64 位。剩余的 32 个最左边的位(共 96 个)用零初始化。所以当你打印它时,你会得到(64个0后跟32个1):
000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111