Home > other >  Is there any way that i can perform bit manipulation with pointers
Is there any way that i can perform bit manipulation with pointers

Time:01-22

Write a function that swaps the highest bits in each nibble of the byte pointed to by the pointer b. (i.e. 0bAxxxBxxx -> 0bBxxxAxxx).

I have a predefined function that is like this -

void swapBits(uint8_t* b);

The solution that I came up with is not working -

void swapBits(uint8_t* b)              
{
     uint8_t bit1;
     uint8_t bit2;
     uint8_t x;
     bit1 = (*b >> 4) & 1;
     bit2 = (*b >> 8) & 1;
     x = bit1 ^ bit2;
     x = x << 4 | x << 8;
     * b = *b ^ x;    
}

CodePudding user response:

You are extracting the low bit in the high nibble and shift out the whole uint8_t for bit2. You need to extract the high bit in both.

Example:

void swapBits(uint8_t* b)              
{
     // shift down the high nibble and get its MSb
     uint8_t bit1 = (*b >> 4) & 0b1000;

     // get the MSb in the low nibble and shift it up
     uint8_t bit2 = (*b & 0b1000) << 4;

     // remove whatever values the MSbs had and replace them with the new values
     *b = (*b & 0b01110111) | bit2 | bit1;
}

0b for binary literals is a gcc extension (but will become standard in C23). If you can't use it, use a plain 8 instead of 0b1000 and 0x77 instead of 0b01110111. I'm using the extension because it makes it easier to see the patterns.

CodePudding user response:

there are couple problems:

  1. to get 4th bit from the right you need to shift 3 times (not four)
  2. xor is probably not what you need to use

here is fixed version:

void swapBits(uint8_t* b)              
{
     uint8_t bit1;
     uint8_t bit2;
     bit1 = ((*b >> 3) & 1) << 7; // get bit from one position and put it into another
     bit2 = ((*b >> 7) & 1) << 3;
     *b = (*b & 0x77) | bit1 | bit2; // clear already extracted bits and reset with new values
}

CodePudding user response:

The major problem in your code is x = x << 4 | x << 8;... Here you are setting both b4(!) and the nonexistent b8(!) to be the same value (0 or 1). This is not "swapping" the bits if they began with opposite values.

XOR will work, but needs some work... The nice part about this is that the "mask" (here hardcoded as 0x88) can be changed to swap any pair of bits in the byte.

#include <stdio.h>

void swapb3b7( uint8_t *b ) {
    uint8_t m = 0x88; // the mask

    if(
        *b&m        // one or both bits set
    &&              // AND
        (*b&m) != m // is not both (need to swap)
    )
        *b = (uint8_t) (
                *b & ~m     // mask for 6 unaffected bits
            |               // OR'd with
                (*b^m)&m ); // the XOR of interesting bits, masked to just b7 and b3
}

int main( void ) {
    uint8_t n[] = { 0x00, 0x08, 0x80, 0x88, 0x90, 0xA0, 0x0A, 0xF7 };

    for( size_t i = 0; i < sizeof n/sizeof n[0]; i   ) {
        printf( "x ", n[i] );
        swapb3b7( &n[i] );
        printf( "x\n", n[i] );
    }

    return 0;
}
00 00
08 80
80 08
88 88
90 18
a0 28
0a 82
f7 7f

Removing the comments from the function shows it somewhat better for those who are conversant with C.

void swapb3b7( uint8_t *b ) {
    uint8_t m = 0x88; // the mask

    if( *b&m && (*b&m) != m )
        *b = (uint8_t) (*b & ~m | (*b^m)&m );
}
  • Related