繁体   English   中英

如何设置特定位?

[英]How to set specific bits?

假设我有一个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的下一个7位和val5的最后一位。

结果将是这样: 1010 0000 0000 1000

我只发现了如何处理某一特定位,但没有找到“组”。 (移位或位集)

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

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

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位。 1左移4位将产生00010000 (二进制)。 从中减去一个,然后清除设置的一位,并设置所有比该位低的位,在本示例中为00001111 这给我们设置了第一个最低有效位。 当我们做一个逐位AND那和输入之间,在输入中设置的任何更高的位在结果中清除。

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

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字段,并让编译器为您执行所有这些操作。

finalvle = 0;
finalvle = (val1&0x01)<<15;
finalvle += (val2&0x07)<<12;
finalvle += (val3&0x0f)<<8
finalvle += (val4&0xfe)<<1;
finalvle += (val5&0x01);

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

使用shift <<来“向左移动字节”:

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

然后,您可以使用按位或| 将其放置在正确的位置(假设您试图覆盖的位上的所有零均为零)。

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

编辑:请注意,@ Inspired的答案还说明了将某些位区域清零。 它总体上说明了如何正确实施它。

试试这个代码:

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

移位是您要设置的位的位置

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM