我想对一个变量进行位移位,然后把移出的位存储在布尔值中。类似于:
unsigned int i = 1; bool b = rshift(&i); // i now equals 0 and b is set to true
如何才能做到这一点?
ygya80vv1#
您必须捕获移位 * 之前 * 的位:
bool rshift(unsigned int* p) { bool ret = (*p) & 1; *p >>= 1; return ret; }
vatpfxk52#
你不知道。你得在换班前测试一下:
bool rshift( unsigned& i ) { bool results = (i & 0x01) != 0; i >>= 1; return results; }
(This对于右移位来说很简单。对于左移位来说,你必须知道字中的位数。)
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; }
pxy2qtax4#
如果你正在寻找一个旋转功能,你可以尝试以下。首先,使用一个 meta函数来获取要旋转的值的位数(注意:8*sizeof(T)将不是可移植;该标准仅规定至少8比特):
8*sizeof(T)
#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 ...
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位或更多位。
int
int32_t
int64_t
i
1
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); } } }
6条答案
按热度按时间ygya80vv1#
您必须捕获移位 * 之前 * 的位:
vatpfxk52#
你不知道。你得在换班前测试一下:
(This对于右移位来说很简单。对于左移位来说,你必须知道字中的位数。)
wkftcu5l3#
要对任何班次和任何类型执行此操作,请反向操作(以检查是否丢失了某些内容)。
pxy2qtax4#
如果你正在寻找一个旋转功能,你可以尝试以下。
首先,使用一个 meta函数来获取要旋转的值的位数(注意:
8*sizeof(T)
将不是可移植;该标准仅规定至少8比特):接下来,定义一个向右旋转的函数,它通过右移和左移来实现,右移和左移在其他情况下会被抵消:
具有诊断功能进行检测,并测试:
输出量:
左旋转可以类似地实现,或者根据右旋转来实现。
至于性能,g++会检测到这个习惯用法,并在x86和amd 64上使用一个旋转指令。
vddsk6oq5#
以下是到目前为止提出的建议的替代方案:
这里假设
int
就是int
现在的意思,即int32_t
,它将它复制到int64_t
中,然后执行移位,将高32位复制到i
中,然后将低32位(包含移位后的1
)作为bool返回。我不知道这是否比其他方法更快。这种通用方法的 * 附加好处 * 是它可以用于检索多个位,例如,如果你移位2位或更多位。
t30tvxxf6#
下面是一个用于位抓取的小C#演示: