如何从 256 位消息中获取特定位?

How to grab specific bits from a 256 bit message?

我正在使用 winsock 接收 256 位长的 udp 消息。我使用 8 个 32 位整数来保存数据。

int32_t dataReceived[8];   

recvfrom(client, (char *)&dataReceived, 8 * sizeof(int), 0, &fromAddr, &fromLen);

我需要抓取特定位,例如位 #100、#225、#55 等。所以有些位会在 dataReceived[3] 中,有些会在 dataReceived[4] 中,等等。

我想我需要对每个数组进行位移,但事情变得复杂了。我接近这一切都错了吗?

当您从 0 开始计算位和字节时:

int bit_needed = 100;

所以:

int byte = int(bit_needed / 8);
int bit = bit_needed % 8;
int the_bit = dataReceived[byte] & (1 << bit);

如果请求的位包含 0,则 the_bit 将为零。如果它是 1,那么 the_bit 将保留字节中该位序号位置的 2 次方。

您可以编写一个小函数来完成这项工作。

uint8_t checkbit(uint32_t *dataReceived, int bitToCheck)
{
  byte = bitToCheck/32;
  bit = bitToCheck - byte*32;
  if( dataReceived[byte] & (1U<< bit))
    return 1;
  else 
    return 0;
}

请注意,如果您使用位移位,则应使用 uint32_t 而不是 int32_t。有符号整数移位会导致不希望的结果,尤其是当 MSbit 为 1.

为什么缓冲区元素使用 int32_t 类型而不是 uint32_t

我通常使用这样的东西:

int bit_needed = 100;
uint32_t the_bit = dataReceived[bit_needed>>5] & (1U << (bit_needed & 0x1F));

或者你可以使用这个(但它不适用于登录有符号整数):

int bit_needed = 100;
uint32_t the_bit = (dataReceived[bit_needed>>5] >> (bit_needed & 0x1F)) & 1U;

在其他答案中,您只能访问每个 int32_t 中的低 8 位。

您可以使用 C 或 C++ 中的宏来检查特定位:

#define bit_is_set(var,bit)     ((var) & (1 << (bit)))

然后是一个简单的 if:

if(bit_is_set(message,29)){
//bit is set
}