Search code examples
cintegerbit-manipulationbitbyte-shifting

How to swap first and last nibbles in given integer [32 bits]


Suppose :

No = 77
77 in binary [32 bits] : 0000 0000 0000 0000 0000 0000 0100 1101

I have to swap first and last nibble:

i.e :                    1101 0000 0000 0000 0000 0000 0100 0000

I was doing something like this:

no << 32 | no >> 32

Then in a loop anding it with 1 and printing. But it does not work out.

#include<stdio.h>

int main()
{

    int decimalNumber;
    printf("Enter your decimal number: ");
    scanf("%d", &decimalNumber);
    int i, j;
    
    /* Binary conversion */
    for(i=31;i>=0;i--)
    {

        printf("%d", (decimalNumber >> i) & 1);
    }
    printf("\n");
    printf("After nibble swapping: \n");
    /* Nibble swapping */
    decimalNumber = (decimalNumber>>28) | (decimalNumber<<28);
    for(i=31;i>=0;i--)
    {
        printf("%d",((decimalNumber>>i)&1 ? 1 : 0));
    }
    printf("\n");
    return 0;
}

Solution

  • swap first and last nibbles in given integer (32 bits)

    OP's decimalNumber = (decimalNumber>>28) | (decimalNumber<<28); fails as the | or's the data, not replace it. Also shifting by 28 shifts the middle bits, which need to remain in place.


    • Use unsigned types to not shift into or out of the sign bit.

    • For a fixed sized tasks, consider using fixed sized types from #include <stdint.h>.

    • Print data with %X to better see what is happening.

        uint32_t uvalue = decimalNumber;
        printf("Before %lu\n", (unsigned long) uvalue);   // In decimal
        printf("Before 0x%lX\n", (unsigned long) uvalue); // In hexadecimal
    
        // Get first (most significant) and last (least significant) nibble.
        uint32_t first_nibble = uvalue >> (32-4);
        uint32_t last_nibble = uvalue & 0xF;
    
        // zero out the first and last nibble.
        uvalue &= 0x0FFFFFF0; 
        // Now "or" in the replacement nibbles.
        uvalue |= first_nibble;
        uvalue |= last_nibble << (32-4);
    
        printf("After 0x%lX\n", (unsigned long) uvalue);
        printf("After %lu\n", (unsigned long) uvalue);
    

    For those who like one-liners

    printf("After %lu\n", (unsigned long) (
        (((uint32_t) decimalNumber) & 0xF) << 28) |
        ((uint32_t) decimalNumber) & 0x0FFFFFF0) |
        ((uint32_t) decimalNumber) >> 28) |
        )); 
    

    Some would consider the first nibble as the least significant nibble. Whatever is first or last makes little difference here as they are swapped.