简体   繁体   English

c 中的位操作和屏蔽

[英]Bit manipulation and masking in c

I am working on some c problems.我正在处理一些 c 问题。 I have one process that needs to be executed and has bit manipulations.我有一个进程需要执行并且有位操作。 I have 2 variables with uint8 type say uint8 bit_Part1 & uint8 bit_Part2 (U8 each).我有 2 个 uint8 类型的变量,例如uint8 bit_Part1uint8 bit_Part2 (每个为 U8)。 I want to add values to these variables having values one is U4 and other U6 like U4_part1 and U6_part2 and one boolean value Bool_Part3 I want to place them into these uint8 bit_Part1 & uint8 bit_Part2 structure as below我想为这些变量添加值,一个是U4 ,另一个是U6 ,如U4_part1U6_part2 ,还有一个 boolean 值Bool_Part3我想将它们放入这些uint8 bit_Part1uint8 bit_Part2结构中,如下所示

在此处输入图像描述

So far i tried shifting like:到目前为止,我尝试像这样移动:

Its psudo code:它的伪代码:

uint8 bitman_u8_part1 =0;
    uint8 bitman_u8_part2 =0;
    bitman_u8_part1 |= ((uint8)(U4_Part1));  // 0000\\\\ 
    bitman_u8_part1 | = ((uint8)((U6_Part2 >> 2)<<4));// append 0000 for the empty 
    bitman_u8_part2 | =((uint8)(EC2_TCH_BITMAP_U6_Part2<<4));
    bitman_u8_part2 | =((bool)BOOL_Part3 & 1<<4);

Here is an example of what I expect to see:这是我希望看到的示例:

If U4_part1=0111, U6_Part2=001111, Bool_Part3=1(true)如果 U4_part1=0111,U6_Part2=001111,Bool_Part3=1(真)

then the expected result is: bit_Part1 & uint8 bit_Part2 both will contain data -> 00000|1|00||1111|0111那么预期的结果是:bit_Part1 & uint8 bit_Part2 都将包含数据 -> 00000|1|00||1111|0111

(note I have added | just for separation between data || is for separation of uint8 bit_Part1 & uint8 bit_Part2). (注意我添加了 | 只是为了数据之间的分离 || 是为了分离 uint8 bit_Part1 和 uint8 bit_Part2)。

Additional values are in uint8 bit_Part2 are filled with 0, compare with picture above (& U4 means value with 4 bits U6 as in with value with 6 bits) uint8中的附加值bit_Part2用0填充,对比上图(&U4表示4位的值,U6表示6位的值)

How can i do it?我该怎么做?

UPDATE:更新:

Something that i have tried again:我再次尝试过的东西:

 unsigned int U4_data1 = 12;    /* 60 = 0000 1100 */  
   unsigned int U6_data2 = 53;  /* 21 = 0011 0101 */
   unsigned int Bool_data3 =1;
   unsigned int U8_part1 =0;
   unsigned int U8_part2 = 0;
   U8_part1 = U4_data1;
   U8_part1 |= (U6_data2<<4);
   printbinary(U8_part1);
   U8_part2 |= U6_data2>>4;
   U8_part2 |= (Bool_data3)<<2;
// Assemble the pieces in a temporary object:
uint16_t temp =   Bool_Part3 << 10
                | U6_part2   <<  4
                | U4_part1   <<  0;

// Redivide the temporary object into the destination parts:
uint8_t bit_Part1 = temp >> 0;
uint8_t bit_Part2 = temp >> 8;

If Bool_Part3 has some integer type that you are calling Boolean even though it is not a standard _Bool or bool (declared in <stdbool.h> ) type and may have a value other than 0 or 1, then an appropriate way to ensure 0 or 1 is inserted in the result is to cast it to _Bool , as with:如果Bool_Part3有一些 integer 类型,你正在调用 Boolean 即使它不是标准的_Boolbool (在<stdbool.h>中声明)类型并且可能有一个不是 0 或 1 的值,那么一个适当的方法来确保 0 或在结果中插入 1 是将其转换为_Bool ,如下所示:

uint16_t temp = (_Bool) Bool_Part3 << 10 …

While you can use other idioms, such as !!Bool_Part3 , the cast has the advantage of explicitly expressing the desired operation, a conversion to 0 or 1. (While programmers 30 years ago had to use various workarounds in C, there is no reason to program kludges the way people did decades ago when modern expressions are available.)虽然您可以使用其他习语,例如!!Bool_Part3 ,但强制转换的优点是可以显式表达所需的操作,转换为 0 或 1。(虽然 30 年前的程序员不得不在 C 中使用各种变通方法,但没有理由以人们几十年前现代表达方式可用时的方式来编程 kludges。)

Notes:笔记:

  • uint8_t and uint16_t are declared in <stdint.h> . uint8_tuint16_t<stdint.h>中声明。
  • Shifts by zero are shown for illustration and uniformity.为了说明和均匀性,显示了零位移。 They may be omitted.它们可以被省略。

I would suggest something along these lines:我会建议沿着这些思路:

#define LOW_4_MASK 0xF
#define LOW_2_MASK 3
#define BOOL_PART3_BIT = 1 << 2;

bit_Part1 = (U4_Part1 & LOW_4_MASK) | ((U6_part2 & LOW_4_MASK) << 4);
bit_Part2 = (U6_part2 >> 4) & LOW_2_MASK;

if (Bool_Part3)
    bit_Part2 |= BOOL_PART3_BIT;

I don't know the types of all your variables here, or whether there exists the possibility of having other bits set, outside the six bit range of U6_part2 , for example.我不知道这里所有变量的类型,或者是否存在设置其他位的可能性,例如U6_part2的六位范围之外。 The masking prevents stray bits, set in error, from propagating into your resulting bit_Part1 and bit_Part2 variables.屏蔽可防止错误设置的杂散位传播到生成的bit_Part1bit_Part2变量中。

I handled the boolean separately because a boolean in much C code including your excerpt as written, is an integer (only newer C standard have modified this, and much C code does not use the newer bool definitions);我单独处理了 boolean,因为 boolean 在很多 C 代码中,包括您所写的摘录,是一个 integer(只有更新的 C 标准修改了这个,很多 C 代码不使用新的 bool 定义); any non-zero value counts as "true".任何非零值都算作“真”。 If you come into this piece of code with Bool_Part3 set to, for example, 0xFFF0, you certainly do not want to OR it into your result.例如,如果您将Bool_Part3设置为 0xFFF0 并进入这段代码,您当然不希望将它与结果进行“或”运算。 Even if you mask it to the lowest bit, you may not get the correct result.即使你把它屏蔽到最低位,你也可能得不到正确的结果。

Here is another method using union.这是使用 union 的另一种方法。 Just replace 1 with your boolean variable, 15 with U6 and 7 with U4.只需将 1 替换为您的 boolean 变量,将 15 替换为 U6,将 7 替换为 U4。


#include <stdio.h>

int main()
{

    struct st_bitman_u8 {
        unsigned char part1;
        unsigned char part2;
    }bitman_u8;
    
    union Data {
        short sum;
        struct st_bitman_u8 _bitman_u8;
    }data;
    
   
    short sum1 = 1 << 10; //1 is Bool_Part3
    short sum2 = 15 << 4; //15 is U6_Part2
    short sum3 = 7;       //7 is U4_part1
   
    data.sum = sum1+sum2+sum3;
    
    printf("part1 %d part2 %d",data._bitman_u8.part1, data._bitman_u8.part2);
    return 0;
}

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

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