如何检查我的字节标志?

时间:2020-03-06 14:39:38  来源:igfitidea点击:

我使用一个字节来存储诸如" 10101010"之类的标志,并且我想知道如何验证特定位是" 1"还是" 0"。

解决方案

我们可以使用AND运算符。例如,我们有:10101010,并且想要检查第三个位,我们可以执行:(10101010 AND 00100000),如果得到00100000,我们知道我们在第三个位置有标志。

byte THIRDBIT = 4; // 4 = 00000100 i.e third bit is set

int isThirdBitSet(byte in) {
 return in & THIRDBIT; // Returns 1 if the third bit is set, 0 otherwise
}

我们可以按照Daok的说明进行操作,然后对上一个AND操作的结果进行逐位或者运算。在这种情况下,最终结果将为1或者0。

这是一个可以用来测试任何所需位的函数:

bool is_bit_set(unsigned value, unsigned bitindex)
{
    return (value & (1 << bitindex)) != 0;
}

一点解释:

左移位运算符(<<)用于创建位掩码。 (1 << 0)等于00000001,(1 << 1)等于00000010,(1 << 3)等于00001000,依此类推。因此,将0移位会测试最右位。 31的移位将是32位值的最左位。

按位与运算符(&)给出的结果是,设置了所有在两侧都为1的位。范例:1111&0001 = 0001; 1111&0010 == 0010; 0000&0001 =0000。因此,如果关联位的值为1,则表达式(值&(1 <<位索引))将返回位掩码;如果关联位为0,则表达式将返回0。

最后,我们只检查结果是否为非零。 (实际上可以将其排除在外,但我想明确指出。)

作为@Daoks答案的扩展

在进行位操作时,非常了解位运算符确实很有帮助。

C中的按位" AND"运算符也是,因此我们要执行的操作是:

unsigned char a = 0xAA; // 10101010 in hex
unsigned char b = (1 << bitpos); //Where bitpos is the position you want to check

if(a & b) {
    //bit set
}

else {
    //not set
}

在上面,我使用按位"与"(C中的&)来检查是否设置了特定位。我还使用了两种不同的方式来表示二进制数。我强烈建议我们查看上面的Wikipedia链接。

使用按位(不合逻辑!),然后将值与位掩码进行比较。

if (var & 0x08) {
  /* the fourth bit is set */
}

传统上,要检查是否设置了最低位,这将类似于:

int MY_FLAG = 0x0001;
if ((value & MY_FLAG) == MY_FLAG)
    doSomething();

到目前为止,没有人错,但是提供一种检查任意位的方法:

int checkBit( byte in, int bit )
{
  return in & ( 1 << bit );
}

如果函数返回非零值,则该位置1.

如果我们使用的是C ++,并且允许使用标准库,建议我们将标志存储在位集中:

#include <bitset>
//...
std::bitset<8> flags(someVariable);

这样我们就可以使用[]索引运算符检查并设置标志。

如果我们喜欢在这样的各个领域工作,那么Kristopher Johnson的答案非常好。我更喜欢通过使用C中的位字段来使代码更易于阅读。

例如:

struct fieldsample
{
  unsigned short field1 : 1;
  unsigned short field2 : 1;
  unsigned short field3 : 1;
  unsigned short field4 : 1;
}

在这里,我们有一个简单的结构,其中包含四个字段,每个字段的大小为1位。然后,我们可以使用简单的结构访问来编写代码。

void codesample()
{
  //Declare the struct on the stack.
  fieldsample fields;
  //Initialize values.
  fields.f1 = 1;
  fields.f2 = 0;
  fields.f3 = 0;
  fields.f4 = 1;
  ...
  //Check the value of a field.
  if(fields.f1 == 1) {}
  ...
}

我们可以获得相同的小尺寸优势,加上可读的代码,因为我们可以在结构内部为字段赋予有意义的名称。