比特集是如何真正工作的

How do bitsets really work

本文关键字:何真正 工作      更新时间:2023-10-16

我在SRT模拟器上工作,在实现中使用std::bitset<size>。我以为我很了解它们,直到我做到了:

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

从本质上讲,发生的事情是,即使在比特集变短后,比特集也会以某种方式保存额外的信息比特,然后每次调用Partition<16, 4>(C, Bs[i], 4)时,它们都会被推回到C上。但是,我的问题是,为什么?这些值不应该保存在内存中,即使它们是,每次调用Bs[i] = Partition<16, 4>(A, i * 4)时我都会创建新的对象,所以这些值不应出现。

任何解释都会有帮助。

感谢对我最初帖子的有益评论,我发现问题不在于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是如何做到这一点的。