如何从位移中获得“丢失”位?

时间:2012-02-27 08:24:44

标签: c++ visual-c++ bit-manipulation

我想对一个变量进行位移,并将一个位移出一个布尔值。

类似的东西:

unsigned int i = 1;
bool b = rshift(&i); // i now equals 0 and b is set to true

如何实现这一目标?

5 个答案:

答案 0 :(得分:13)

你必须在班次之前捕捉

bool rshift(unsigned int* p) {
    bool ret = (*p) & 1;
    *p >>= 1;
    return ret;
}

答案 1 :(得分:5)

你没有。你必须在班次之前测试它:

bool
rshift( unsigned& i )
{
    bool results = (i & 0x01) != 0;
    i >>= 1;
    return results;
}

(这对于右移是很简单的。对于左移,你必须知道 单词中的位数。)

答案 2 :(得分:3)

要为任何班次和任何类型执行此操作,请执行相反操作(以检查是否丢失了某些内容)。

template <typename T> bool rshift(T& val) {
  T const original = val;
  return ((val >>= 1) << 1) != original;
}
template <typename T> bool lshift(T& val) {
  T const original = val;
  return ((val <<= 1) >> 1) != original;
}

答案 3 :(得分:1)

如果您正在寻找旋转功能,可以尝试以下操作。

首先,有一个元函数来获取待旋转值的位数(注意:8*sizeof(T)不可移植;标准只能指定至少8位):

#include <climits>
template <typename T>
struct bits { enum { value = CHAR_BIT * sizeof(T) }; };

接下来,定义一个正确旋转的功能。它通过按预期应用右移来实现这一目的,并通过左移来提升将被取消的内容:

template <unsigned int N, typename T>
T rotate_right (T value)
{
    enum { left = bits<T>::value - N };
    return (value>>N) | (value<<left);
}

具有测试和测试的诊断功能:

#include <iostream>

template <typename T>
void print_bits (std::ostream &os, T value)
{
    for (unsigned int i=bits<T>::value; i!=0; --i)
        os << ((value>>(i-1))&1);
}

    int main () {
    char c = 1,
         c_ = rotate_right<1>(c);

    unsigned long long ull = 0xF0F0C0C050503030, 
                       ull_ = rotate_right<63>(ull);

    std::cout << "c ="; print_bits(std::cout, c);  std::cout << '\n';
    std::cout << "c'="; print_bits(std::cout, c_); std::cout << '\n';
    std::cout << "ull ="; print_bits(std::cout, ull);  std::cout << '\n';
    std::cout << "ull'="; print_bits(std::cout, ull_); std::cout << '\n';
}

输出:

c =00000001
c'=10000000
ull =1111000011110000110000001100000001010000010100000011000000110000
ull'=1110000111100001100000011000000010100000101000000110000001100001

左旋转可以类似地实现,也可以实现右旋转。

至于性能,g ++检测成语并在x86和amd64上使用旋转指令。

g++ -std=c++0x -S main.cc
cat main.s

...
sarl %eax
...

答案 4 :(得分:0)

以下是目前提出的建议的替代方案:

bool rshift(int32_t &i) {
  long long i2 = (static_cast<int64_t>(i) << 31);
  i = (i2 >> 32);
  return static_cast<int32_t>(i2);
}

这假定intint这些天通常所说的内容,即int32_t。它将其复制到int64_t,然后执行移位,将高32位复制到i,然后将低32位(包含移位的1)作为布尔值返回。 / p>

我不知道这是否比其他方法更快。这种通用方法的附加好处是它可以用于检索多个比特,例如如果你换2位或更多位。