24

我在从一个字节中获取 n 位时遇到了一些麻烦。

我有一个无符号整数。假设我们的十六进制数是 0x2A,十进制是 42。在二进制中它看起来像这样:0010 1010。我如何获取前 5 位 00101 和接下来的 3 位 010,并将它们放入单独的整数中?

如果有人可以帮助我,那就太好了!我知道如何从一个字节中提取这是简单的

int x = (number >> (8*n)) & 0xff // n being the # byte

我在关于堆栈溢出的另一篇文章中看到了这一点,但我不确定如何从字节中获取单独的位。如果有人可以帮助我,那就太好了!谢谢!

4

6 回答 6

27

整数在机器内部表示为位序列;对我们人类来说幸运的是,编程语言提供了一种以十进制(或十六进制)显示这些数字的机制,但这不会改变它们的内部表示。

您应该修改按位运算符&,|^以及~移位运算符<<and >>,这将帮助您了解如何解决此类问题。

整数的最后 3 位是:

x & 0x7

从最后八位开始的五位是:

x >> 3    // all but the last three bits
  &  0x1F // the last five bits.
于 2013-03-06T19:05:41.103 回答
19

在 C 中“抓取”整数类型的部分是这样的:

  1. 您将所需的位移动到最低位置。
  2. &用来掩盖你想要的位 - 一个意味着“复制这个位”,零意味着“忽略”

所以,在你的例子中。假设我们有一个数字int x = 42;

前 5 位:

(x >> 3) & ((1 << 5)-1);

或者

(x >> 3) & 31;

要获取低三位:

(x >> 0) & ((1 << 3)-1)

或者:

x & 7;
于 2013-03-06T19:06:06.980 回答
10

假设您想要hi顶部的lo位和底部的位。(在您的示例中为 5 和 3)

top = (n >> lo) & ((1 << hi) - 1)
bottom = n & ((1 << lo) - 1)

解释:

对于top,首先去掉较低的位(右移),然后用“全为”掩码屏蔽剩余的位(如果你有一个像 的二进制数0010000,减去一个结果0001111- 与你有相同数量的1s 0-s在原始号码中)。

对于底部它是相同的,只是不必关心最初的转变。

top = (42 >> 3) & ((1 << 5) - 1) = 5 & (32 - 1) = 5 = 00101b
bottom = 42 & ((1 << 3) - 1) = 42 & (8 - 1) = 2 = 010b
于 2013-03-06T19:06:00.430 回答
8

您可以为此使用位域。位域是特殊的结构,您可以在其中以位指定变量。

typedef struct {
  unsigned char a:5;
  unsigned char b:3;
} my_bit_t;

unsigned char c = 0x42;
my_bit_t * n = &c;
int first = n->a;
int sec = n->b;

位字段在http://www.cs.cf.ac.uk/Dave/C/node13.html#SECTION001320000000000000000有更详细的描述

位域的魅力在于,您不必处理移位运算符等。符号很简单。与操作位一样,存在可移植性问题。

于 2013-03-06T20:20:12.157 回答
2

int x = (number >> 3) & 0x1f;

会给你一个整数,其中最后 5 位是 8-4 位,number其他位为零。

相似地,

int y = number & 0x7;

会给你一个整数,最后 3 位设置最后 3 位,number其余部分为零。

于 2013-03-06T19:05:44.777 回答
1

只需摆脱代码中的 8* 即可。

int input = 42;
int high3 = input >> 5;
int low5 = input & (32 - 1); // 32 = 2^5
bool isBit3On = input & 4; // 4 = 2^(3-1)
于 2013-03-06T19:03:47.680 回答