如何检查字节标志,验证特定位是否为1或0?

29

我使用一个字节来存储一些标志,如 10101010,我想知道如何验证特定的位是 1 还是 0

10个回答

57

这里有一个可以用来测试任何的函数:

bool is_bit_set(unsigned value, unsigned bitindex)
{
    return (value & (1 << bitindex)) != 0;
}
说明左移位运算符 << 创建一个 位掩码。例如:
  • (1 << 0) 等于 00000001
  • (1 << 1) 等于 00000010
  • (1 << 3) 等于 00001000
因此,使用0进行的位移测试最右边的位。 32 位值的最左边的位将使用31位移。 按位与运算符 (&) 的结果是:两侧所有位上均为1的位都被设置为1。示例:
  • 1111 & 0001 等于 0001
  • 1111 & 0010 等于 0010
  • 0000 & 0001 等于 0000
因此,如下表达式:
(value & (1 << bitindex))

如果相关位(bitindex)在该位置包含1,则返回位掩码;否则,将返回0(意味着在相关的bitindex位置上不包含1)。

简单来说,该表达式检测结果是否大于

  • 如果Result > 0返回true,表示字节在测试的bitindex位置上有一个1
  • 其他所有情况都会返回false,这意味着结果为零,这意味着在测试的bitindex位置上有一个0

请注意,由于它是布尔值,因此语句中不需要!= 0,但我喜欢明确指出。


我认为当前的功能,在这种情况下返回false是正确的... - Chris Marasti-Georg
1
为什么要进行位移操作我不理解:( - Pokus
1
这只是一个示例,旨在演示如何测试位。在生产代码中,您可能希望添加一些错误检查,但那只会在这里增加噪音。 - Kristopher Johnson
正确。尽管 Kristopher 移位 (1 << 3) 的例子应该是 00001000,我相信。 - mdec
另外,is*是一个保留的命名空间,尽管有些人会认为这是卖弄学问。 - James Antill
显示剩余5条评论

6
作为Patrick Desjardins的回答的延伸:
在进行位运算时,按位运算符的扎实知识确实会非常有帮助。
此外,在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语言中为&)来检查特定的位是否被设置。我还使用了两种不同的二进制数表示方法。我强烈建议您查看上面提供的维基百科链接。

你没有必要在特定的变量中存储位移,我使用它作为按位运算符的示例。但是,如果你不进行位移,你就必须在某个地方使用显式值。我使用的位移是一种简便的方法,可以在这个例子中将 bitpos 设为 2 来执行 00000100 的操作。 - mdec

4

您可以使用AND运算符。例如,您有一个数字10101010,想要检查第三位,您可以执行以下操作:(10101010 AND 00100000)。如果您得到00100000,则表示在第三个位置上的标志位为1。


C语言没有“AND”运算符。此外,您需要使用按位与运算符,而不是逻辑运算符。 - Michael Carman

4

Kristopher Johnson的答案非常好,如果你喜欢像这样处理单个字段。我更喜欢在C中使用位域(bit fields)来使代码更易于阅读。

例如:

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) {}
  ...
}

你可以通过使用结构体在代码中为字段命名,从而获得相同的小尺寸优势和可读性。

2
请注意使用位域的问题在于它们在内存中的布局取决于实现方式,因此可能难以将其与其他程序交换的数据一起使用。 - Kristopher Johnson

3

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

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

这样你就可以使用[]索引运算符来检查和设置标志。


2

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

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

如果函数返回非零值,则该位被设置。

1
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
}

1

1

传统上,要检查最低位是否设置,代码通常会像这样:

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

2
这个测试检查一个特定的位是否被设置,仅限于该位 - Michael Carman

0
使用按位(而非逻辑)AND运算符将值与位掩码进行比较。
if (var & 0x08) {
  /* The fourth bit is set */
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接