bitsets 是如何工作的
How do bitsets really work
我正在使用 SRT 模拟器,并且在我的实现中使用了 std::bitset<size>
s。在我这样做之前,我认为我已经很好地理解了它们:
template <unsigned int larger, unsigned int smaller>
bitset<smaller> Partition(const bitset<larger> &original, unsigned int offset) {
return bitset<smaller>(original.to_ulong() >> offset);
}
template <unsigned int larger, unsigned int smaller>
void Partition(bitset<larger> &location, const bitset<smaller> &value, unsigned int offset) {
location <<= offset;
location ^= bitset<larger>(value.to_ulong());
return;
}
第一个函数旨在获取一个较长的数字,并将特定数量的位划分为一个较短的数字。例如,如果我有 10111010
并且我只想在 std::bitset<4>
中使用 1011
,那么我会调用 Partition<8, 4>(my_larger_number, 4);
。第二个则相反。我可以把一个较短的数字变成一个较长的数字。这两个函数都按预期工作,直到:
int main() {
bitset<16> A("1011101010011000");
cout << "A = " << A << endl;
bitset<4> Bs[4];
bitset<16> C;
for (int i = 0; i < 4; i++) {
Bs[i] = Partition<16, 4>(A, 4 * i);
cout << "B[" << i << "] = " << Bs[i] << endl;
}
for (int i = 3; i >= 0; i--) {
cout << "Value of B[" << i << "] = " << bitset<16>(Bs[i].to_ulong()) << endl;
Partition<16, 4>(C, Bs[i], 4);
cout << "C = " << C << endl;
}
return 0;
}
这个操作的输出是:
A = 1011 1010 1001 1000
B[0] = 1000
B[1] = 1001
B[2] = 1010
B[3] = 1011
Value of B[3] = 0000 0000 0000 1011
C = 0000 0000 0000 1011
Value of B[2] = 0000 0000 1011 1010
C = 0000 0000 0000 1010
Value of B[1] = 0000 1011 1010 1001
C = 0000 1011 0000 1001
Value of B[0] = 1011 1010 1001 1000
C = 0000 1010 0000 1000
本质上,发生的事情是位集以某种方式保存了额外的信息位,即使它们已经变短了,然后每次调用 [= 时它们都会被推回 C
19=]。但是,我的问题是,为什么?这些值不应该保存在内存中,即使它们保存在内存中,我每次调用 Bs[i] = Partition<16, 4>(A, i * 4)
时都会创建新对象,所以这些值不应该显示。
任何解释都会有所帮助。
感谢对我的原始 post 的有益评论,我发现问题不在于 std::bitset
的 C++ 实现,而是 Xcode g++ 中的一些奇怪现象,这我曾经编译它。为了解决这个问题,我创建了 Partition
:
的修改版本
template <unsigned int larger, unsigned int smaller>
bitset<smaller> Partition(const bitset<larger> &original, unsigned int offset) {
bitset<smaller> newValue(0);
newValue = ((original >> offset) & bitset<larger>((1 << smaller) - 1)).to_ulong();
return newValue;
}
本质上,我所做的只是屏蔽第一个 smaller
位,然后将其他位设为 0。我不想这样做,因为它增加了复杂性,但它似乎是唯一可用的解决方案不知道 Xcode 是如何做到这一点的。
我正在使用 SRT 模拟器,并且在我的实现中使用了 std::bitset<size>
s。在我这样做之前,我认为我已经很好地理解了它们:
template <unsigned int larger, unsigned int smaller>
bitset<smaller> Partition(const bitset<larger> &original, unsigned int offset) {
return bitset<smaller>(original.to_ulong() >> offset);
}
template <unsigned int larger, unsigned int smaller>
void Partition(bitset<larger> &location, const bitset<smaller> &value, unsigned int offset) {
location <<= offset;
location ^= bitset<larger>(value.to_ulong());
return;
}
第一个函数旨在获取一个较长的数字,并将特定数量的位划分为一个较短的数字。例如,如果我有 10111010
并且我只想在 std::bitset<4>
中使用 1011
,那么我会调用 Partition<8, 4>(my_larger_number, 4);
。第二个则相反。我可以把一个较短的数字变成一个较长的数字。这两个函数都按预期工作,直到:
int main() {
bitset<16> A("1011101010011000");
cout << "A = " << A << endl;
bitset<4> Bs[4];
bitset<16> C;
for (int i = 0; i < 4; i++) {
Bs[i] = Partition<16, 4>(A, 4 * i);
cout << "B[" << i << "] = " << Bs[i] << endl;
}
for (int i = 3; i >= 0; i--) {
cout << "Value of B[" << i << "] = " << bitset<16>(Bs[i].to_ulong()) << endl;
Partition<16, 4>(C, Bs[i], 4);
cout << "C = " << C << endl;
}
return 0;
}
这个操作的输出是:
A = 1011 1010 1001 1000
B[0] = 1000
B[1] = 1001
B[2] = 1010
B[3] = 1011
Value of B[3] = 0000 0000 0000 1011
C = 0000 0000 0000 1011
Value of B[2] = 0000 0000 1011 1010
C = 0000 0000 0000 1010
Value of B[1] = 0000 1011 1010 1001
C = 0000 1011 0000 1001
Value of B[0] = 1011 1010 1001 1000
C = 0000 1010 0000 1000
本质上,发生的事情是位集以某种方式保存了额外的信息位,即使它们已经变短了,然后每次调用 [= 时它们都会被推回 C
19=]。但是,我的问题是,为什么?这些值不应该保存在内存中,即使它们保存在内存中,我每次调用 Bs[i] = Partition<16, 4>(A, i * 4)
时都会创建新对象,所以这些值不应该显示。
任何解释都会有所帮助。
感谢对我的原始 post 的有益评论,我发现问题不在于 std::bitset
的 C++ 实现,而是 Xcode g++ 中的一些奇怪现象,这我曾经编译它。为了解决这个问题,我创建了 Partition
:
template <unsigned int larger, unsigned int smaller>
bitset<smaller> Partition(const bitset<larger> &original, unsigned int offset) {
bitset<smaller> newValue(0);
newValue = ((original >> offset) & bitset<larger>((1 << smaller) - 1)).to_ulong();
return newValue;
}
本质上,我所做的只是屏蔽第一个 smaller
位,然后将其他位设为 0。我不想这样做,因为它增加了复杂性,但它似乎是唯一可用的解决方案不知道 Xcode 是如何做到这一点的。