c++ 如何从位移位中获取“丢失”位?

oknwwptz  于 2022-12-05  发布在  其他
关注(0)|答案(6)|浏览(169)

我想对一个变量进行位移位,然后把移出的位存储在布尔值中。
类似于:

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

如何才能做到这一点?

ygya80vv

ygya80vv1#

您必须捕获移位 * 之前 * 的位:

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

vatpfxk52#

你不知道。你得在换班前测试一下:

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

(This对于右移位来说很简单。对于左移位来说,你必须知道字中的位数。)

wkftcu5l

wkftcu5l3#

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

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;
}
pxy2qtax

pxy2qtax4#

如果你正在寻找一个旋转功能,你可以尝试以下。
首先,使用一个 meta函数来获取要旋转的值的位数(注意: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和amd 64上使用一个旋转指令。

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

...
sarl %eax
...
vddsk6oq

vddsk6oq5#

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

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

这里假设int就是int现在的意思,即int32_t,它将它复制到int64_t中,然后执行移位,将高32位复制到i中,然后将低32位(包含移位后的1)作为bool返回。
我不知道这是否比其他方法更快。这种通用方法的 * 附加好处 * 是它可以用于检索多个位,例如,如果你移位2位或更多位。

t30tvxxf

t30tvxxf6#

下面是一个用于位抓取的小C#演示:

using System;
class BitToBoolArray {
  static void Main() {
  
  ushort guiMask = 0b1100_1100_0011_0011;
  
    bool[] boxEnabled = new bool[16]; 
    
    for (int i=0;i<16;guiMask>>=1,++i) 
    {
        
        bool bit =  (guiMask & 0x0001) == 1 ;
        boxEnabled[i] = bit;
        Console.WriteLine("\r\nBit position: {0} , Bit: {1}",i,bit);
    }
    

  }
}

相关问题