简体   繁体   English

如何设置特定位?

[英]How to set specific bits?

Let's say I've got a uint16_t variable where I must set specific bits. 假设我有一个uint16_t变量,必须在其中设置特定位。

Example: 例:

uint16_t field = 0;

That would mean the bits are all zero: 0000 0000 0000 0000 那将意味着这些位全为零: 0000 0000 0000 0000

Now I get some values that I need to set at specific positions. 现在,我得到了一些需要在特定位置设置的值。

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

The structure how to set the bits is the following 位的设置方法如下

0|000|  0000| 0000 000|0

val1 should be set at the first bit on the left. val1应该设置在左侧的第一位。 so its only one or zero. 所以它只有一或零

val2 should be set at the next three bits. val2应该设置在接下来的三位。 val3 on the next four bits. val3接下来的四位。 val4 on the next seven bits and val5 one the last bit. val4的下一个7位和val5的最后一位。

The result would be this: 1010 0000 0000 1000 结果将是这样: 1010 0000 0000 1000

I only found out how to the one specific bit but not 'groups'. 我只发现了如何处理某一特定位,但没有找到“组”。 (shift or bitset) (移位或位集)

Does anyone have an idea how to solve this issue? 有谁知道如何解决这个问题?

There are (at least) two basic approaches. 有(至少)两种基本方法。 One would be to create a struct with some bitfields: 一种方法是创建具有某些位域的结构:

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;

To get the 16-bit value, you could (for one example) create a union of that struct with a uint16_t . 要获得16位值,您可以(例如,一个示例)使用uint16_t创建该结构的并集。 Just one minor problem: the standard doesn't guarantee what order the bit fields will end up in when you look at the 16-bit value. 只是一个小问题:标准不保证当您查看16位值时,位字段将以什么顺序结束。 Just for example, you might need to reverse the order I've given above to get the order from most to least significant bits that you really want (but changing compilers might muck things up again). 仅举例来说,您可能需要颠倒上面给出的顺序,以将顺序从您真正想要的最高有效位降到最低有效位(但是更改编译器可能会再次使事情变得糟糕)。

The other obvious possibility would be to use shifting and masking to put the pieces together into a number: 另一个明显的可能性是使用移位和遮罩将片段组合成一个数字:

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

For the moment, I've assumed each of the inputs starts out in the correct range (ie, has a value that can be represented in the chosen number of bits). 目前,我假设每个输入都在正确的范围内开始(即,具有一个可以用所选位数表示的值)。 If there's a possibility that could be wrong, you'd want to mask it to the correct number of bits first. 如果存在错误的可能性,则需要先将其屏蔽为正确的位数。 The usual way to do that is something like: 这样做的通常方法是:

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

In case you're curious about the math there, it works like this. 如果您对那里的数学感到好奇,它会像这样工作。 Lets's assume we want to ensure an input fits in 4 bits. 假设我们要确保输入适合4位。 Shifting 1 left 4 bits produces 00010000 (in binary). 1左移4位将产生00010000 (二进制)。 Subtracting one from that then clears the one bit that's set, and sets all the less significant bits than that, giving 00001111 for our example. 从中减去一个,然后清除设置的一位,并设置所有比该位低的位,在本示例中为00001111 That gives us the first least significant bits set. 这给我们设置了第一个最低有效位。 When we do a bit-wise AND between that and the input, any higher bits that were set in the input are cleared in the result. 当我们做一个逐位AND那和输入之间,在输入中设置的任何更高的位在结果中清除。

One of the solutions would be to set a K-bit value starting at the N-th bit of field as: 解决方案之一是将从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

Or, if you can use struct instead of uint16_t, you can use Bit fields and let the compiler to perform all these actions for you. 或者,如果可以使用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);

You can use the bitwise or and shift operators to achieve this. 您可以使用按位或和移位运算符来实现此目的。

Use shift << to 'move bytes to the left': 使用shift <<来“向左移动字节”:

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

You can then use bitwise or | 然后,您可以使用按位或| to put it at the right place, (assuming you have all zeros at the bits you are trying to overwrite). 将其放置在正确的位置(假设您试图覆盖的位上的所有零均为零)。

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

Edit: Note that @Inspired's answer also explains with zeroing out a certain area of bits. 编辑:请注意,@ Inspired的答案还说明了将某些位区域清零。 It overall explains how you would go about implementing it properly. 它总体上说明了如何正确实施它。

try this code: 试试这个代码:

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

where shift is position of bit that you wanna set 移位是您要设置的位的位置

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

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