简体   繁体   中英

Bitwise C - Unpacking signed 10 bit numbers from an unsigned int

I've been asked to create a function which will take an unsigned 32bit int and unpack 3 signed 10 bit ints from the unsigned int. The context for this task was an unpacking function, which took a 32bit unsigned int as input and an array of length 3 called xyz and occupied the array with x, y and z co-ordinates unpacked from the original int, with these co-ordinates being 10bit signed ints.

I wrote the following program which seems to work fine for positive values, but not for negative values. I've tried printing the hex values of the output co-ordinates to get a better sense of the underlying binary and everything seems fine to me, but the interpreted number comes out wrong. For signed ints the compiler uses two's complement to interpret the binary.

void coordinates(unsigned int p, int xyz[3]) {
  unsigned int z = ((p << 22) >> 22) & 0x800003FF;
  xyz[0] = (~0 << 32) | (p >> 20) ;
  xyz[1] = (~0 << 32) | (p >> 10) & 0x3FF;
  xyz[2] = (~0 << 32) | z;
}

Let me know if you have any further questions and I'll do my best to answer them.

The following should work for you:

void coordinates(unsigned int p, int xyz[3])
{
    xyz[0] = (p >> 20) & 0x3FF; // Get 10 Bits
    if(xyz[0] & 0x200) // Check MSB
        xyz[0] |= 0xFFFFFC00; // Sign Extend
    xyz[1] = (p >> 10) & 0x3FF;
    if(xyz[1] & 0x200)
        xyz[1] |= 0xFFFFFC00;
    xyz[2] = p & 0x3FF;
    if(xyz[2] & 0x200)
        xyz[2] |= 0xFFFFFC00;
}

int main(void)
{
    int s10[3];
    unsigned int u32 = 0xFFFFFFFF;

    coordinates(u32, s10);
    printf("%08X %08X %08X %08X\n", u32, s10[0], s10[1], s10[2]);
    printf("%d %d %d %d\n", u32, s10[0], s10[1], s10[2]);

    u32 = 0x1FF7FDFF;

    coordinates(u32, s10);
    printf("%08X %08X %08X %08X\n", u32, s10[0], s10[1], s10[2]);
    printf("%d %d %d %d\n", u32, s10[0], s10[1], s10[2]);

    u32 = 0x20080200;

    coordinates(u32, s10);
    printf("%08X %08X %08X %08X\n", u32, s10[0], s10[1], s10[2]);
    printf("%d %d %d %d\n", u32, s10[0], s10[1], s10[2]);

    u32 = 0x00000000;

    coordinates(u32, s10);
    printf("%08X %08X %08X %08X\n", u32, s10[0], s10[1], s10[2]);
    printf("%d %d %d %d\n", u32, s10[0], s10[1], s10[2]);

    return 0;
}

Output

$ gcc main.c -o main.exe; ./main.exe;
FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
-1 -1 -1 -1
1FF7FDFF 000001FF 000001FF 000001FF
536346111 511 511 511
20080200 FFFFFE00 FFFFFE00 FFFFFE00
537395712 -512 -512 -512
00000000 00000000 00000000 00000000
0 0 0 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