1

假设我有一个uint16_t变量,我必须在其中设置特定位。

例子:

uint16_t field = 0;

这意味着这些位都为零:0000 0000 0000 0000

现在我得到了一些需要在特定位置设置的值。

val1=1; val2=2, val3=0, val4=4, val5=0;

如何设置位的结构如下

0|000|  0000| 0000 000|0

val1应该设置在左边的第一位。所以它只有一或零。

val2应设置在接下来的三位。val3在接下来的四位。val4在接下来的七位和val5最后一位。

结果将是这样的: 1010 0000 0000 1000

我只发现了一个特定的位而不是“组”。(移位或位集)

有谁知道如何解决这个问题?

4

5 回答 5

8

有(至少)两种基本方法。一种是创建一个带有一些位域的结构:

struct bits { 
    unsigned a : 1;
    unsigned b : 7;
    unsigned c : 4;
    unsigned d : 3;
    unsigned e : 1;
};

bits b;

b.a = val1;
b.b = val2;
b.c = val3;
b.d = val4;
b.e = val5;

要获得 16 位值,您可以(例如)创建该结构与uint16_t. 只有一个小问题:当您查看 16 位值时,该标准不保证位字段的最终顺序。举例来说,您可能需要颠倒我上面给出的顺序,以获得您真正想要的从最高有效位到最低有效位的顺序(但更改编译器可能会再次搞砸)。

另一个明显的可能性是使用移位和掩码将各个部分组合成一个数字:

int16_t result = val1 | (val2 << 1) | (val3 << 8) | (val4 << 12) | (val5 << 15);

目前,我假设每个输入都在正确的范围内开始(即,具有可以用所选位数表示的值)。如果有可能是错误的,您需要先将其屏蔽为正确的位数。通常的方法是:

uint16_t result = input & ((1 << num_bits) - 1);

如果您对那里的数学感到好奇,它的工作原理是这样的。假设我们要确保输入适合 4 位。左移14 位产生00010000(二进制)。从中减去一位,然后清除设置的一位,并设置所有低于该位的有效位,00001111例如我们的示例。这给了我们第一个最低有效位集。当我们AND在它和输入之间进行逐位处理时,输入中设置的任何高位都会在结果中被清除。

于 2013-06-27T06:10:17.843 回答
1

解决方案之一是设置从第 N 位开始的 K 位值field

uint16_t value_mask = ((1<<K)-1) << N; // for K=4 and N=3 will be 00..01111000
field = field & ~value_mask; // zeroing according bits inside the field
field = field | ((value << N) & value_mask); // AND with value_mask is for extra safety

或者,如果您可以使用 struct 而不是 uint16_t,则可以使用Bit 字段并让编译器为您执行所有这些操作。

于 2013-06-27T06:08:26.247 回答
0
finalvle = 0;
finalvle = (val1&0x01)<<15;
finalvle += (val2&0x07)<<12;
finalvle += (val3&0x0f)<<8
finalvle += (val4&0xfe)<<1;
finalvle += (val5&0x01);
于 2013-06-27T06:08:22.513 回答
0

您可以使用按位或和移位运算符来实现此目的。

使用 shift<<将字节向左移动:

int i = 1;  // ...0001
int j = i << 3 // ...1000

然后,您可以按位使用或|将其放在正确的位置(假设您在尝试覆盖的位处全为零)。

int k = 0;  // ...0000
k |= i // ...0001
k |= j // ...1001

编辑:请注意,@Inspired 的回答还解释了将某个位区域归零。它总体上解释了您将如何正确实施它。

于 2013-06-27T06:09:37.017 回答
0

试试这个代码:

uint16_t shift(uint16_t num, int shift)
{
    return num | (int)pow (2, shift);
}

其中 shift 是您要设置的位的位置

于 2013-06-27T06:13:23.567 回答