0

我看到了其中一位 stackoverflower 同事发布的以下内容,这让我有些目瞪口呆。

有人会在以下代码片段中解释移位操作:

std::vector<bool> a;
a.push_back(true);
a.push_back(false);
//...
for (auto it = a.begin(); it != a.end();) // see 0x for meaning of auto
{
    unsigned b = 0;
    for (int i = 0; i < 8*sizeof(b); ++i)
    {
        b |= (*it & 1) << (8*sizeof(b) - 1 - i);
        ++it;
    }
    // flush 'b'
}
4

3 回答 3

3

8 * sizeof(b) 是可以存储在“b”中的位数(这是一个无符号整数,即通常为 32 或 64 位)。

代码所做的是它将向量'a'中的布尔值打包成'b'中的位。

如果 *it 处的布尔值为 TRUE,则“*it & 1”评估为 1,否则为 0。然后该位左移 32 位减去 1 减去索引“i”,即从零左移到 31 位。这意味着现在“a”的第一个元素将控制“b”上的最高有效位(左移 31),第二个元素将控制“b”上的第二个最高有效位(左移 30)等。请注意,在 C移位是算术的,即无论字节或位顺序如何,x << 1 始终为 x * 2。

例如,如果您的向量具有第一个和第 30 个元素集,则“b”应该在一天结束时包含二进制数 10000000 00000000 00000000 00000100。

于 2009-02-23T18:49:12.687 回答
0

antti.huima 的回答对我来说是正确的。

但是,程序中可能存在错误。外部循环从 a.begin 到 a.end,但是内部循环递增“it”,无论这是否导致“it”超过 a.end。

如果您传递一个“奇数”大小的向量,比如 33 个条目,则结果可能不正确。

如果向量的大小得到保证,这可能不是错误(但也许应该测试长度是否有效)。

于 2009-02-23T18:55:23.563 回答
0

那里发生了什么:

(*it & 1)

这应该是 0 或 1,具体取决于布尔值是真还是假;但是请注意,布尔值始终为 0 或 1,因此这可能只是 (unsigned)*it

<< (8*sizeof(b) - 1 - i)

这是一个移位,它将位从最右边的位置移动到左边的第i个位置。我们正在移动一个最多设置一个位的数字,所以这将设置第i个最左边的位或不设置。其余位为零。

b |= ...

b这将设置在 RHS 中的那些位。

i++;

转到下一个输入数字。注意保持在输入范围内。

这意味着整个事物将在 中设置位b,对应于为真的向量元素。

于 2009-02-23T18:57:03.450 回答