假设我有一个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
我只发现了一个特定位而不是“组”。 (移位或bitset)
有谁知道如何解决这个问题?
答案 0 :(得分:7)
有(至少)两种基本方法。一种方法是创建一个包含一些位域的结构:
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
时,在结果中清除输入中设置的任何更高位。
答案 1 :(得分:1)
其中一个解决方案是设置从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 fields并让编译器为您执行所有这些操作。
答案 2 :(得分:0)
finalvle = 0;
finalvle = (val1&0x01)<<15;
finalvle += (val2&0x07)<<12;
finalvle += (val3&0x0f)<<8
finalvle += (val4&0xfe)<<1;
finalvle += (val5&0x01);
答案 3 :(得分:0)
您可以使用按位或移位运算符来实现此目的。
使用shift <<
'向左移动字节':
int i = 1; // ...0001
int j = i << 3 // ...1000
然后你可以使用按位或|
将它放在正确的位置,(假设你在要覆盖的位上都有零)。
int k = 0; // ...0000
k |= i // ...0001
k |= j // ...1001
编辑:请注意,@ Inspired的答案也解释了将某个区域清零。它总体上解释了如何正确实施它。
答案 4 :(得分:0)
试试这段代码:
uint16_t shift(uint16_t num, int shift)
{
return num | (int)pow (2, shift);
}
其中shift是你想要设置的位的位置