[英]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.