简体   繁体   中英

Bit manipulation and masking in c

I am working on some c problems. 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). 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

在此处输入图像描述

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)

then the expected result is: bit_Part1 & uint8 bit_Part2 both will contain data -> 00000|1|00||1111|0111

(note I have added | just for separation between data || is for separation of 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)

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:

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.)

Notes:

  • uint8_t and uint16_t are declared in <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. The masking prevents stray bits, set in error, from propagating into your resulting bit_Part1 and bit_Part2 variables.

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); 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. Even if you mask it to the lowest bit, you may not get the correct result.

Here is another method using union. Just replace 1 with your boolean variable, 15 with U6 and 7 with 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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