buddy2891
buddy2891

Reputation: 427

Splitting an Int to 3 bytes and back in C

I have the following code to split an int into 3 bytes and then back:

#include <stdio.h>
#include <stdint.h>

int main()
{
    int a = 626;
    uint8_t msb = (a >> 16) & 0xff;
    uint8_t msb1 = (a >> 8) & 0xff;
    uint8_t lsb = a & 0xff;

    printf("MSB: %u, MSB1: %u, LSB: %u\n", msb, msb1, lsb);

    uint8_t h1 = msb << 16;
    uint8_t h2 = msb1 << 8;
    uint8_t h3 = lsb & 0xff;

    int b = h1 | h2 | h3;

    printf("Final: %d\n", b);

    return 0;
}

When I run this code the output is as follows: MSB: 0, MSB1: 2, LSB: 114 Final: 114

I should get Final as 626 but I get 114. It would be great if someone could help out. Thanks

Upvotes: 2

Views: 2223

Answers (3)

LPs
LPs

Reputation: 16223

A possible solution is

#include <stdio.h>
#include <stdint.h>

int main(void)
{
    int a = 626;
    uint8_t msb = (a >> 16) & 0xff;
    uint8_t msb1 = (a >> 8) & 0xff;
    uint8_t lsb = a & 0xff;

    printf("MSB: %u, MSB1: %u, LSB: %u\n", msb, msb1, lsb);

    uint32_t b = msb;
    b = (b<<8) | msb1;
    b = (b<<8) | lsb;

    printf("Final: %d\n", b);

    return 0;
}

As you can see:

  1. I changed the type of b: left shift signed values can be UB.

6.5.7/4 [...] If E1 has a signed type and nonnegative value, and E1×2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

  1. What you did it was right shift a char (8 bits) right by 8 or 16, which means you lost all your bits. So as you can see you can, first of all, assign first value to a larger variable (unsigned int) and after that shift it.

Upvotes: 4

Tezirg
Tezirg

Reputation: 1649

First make sure you aren't mixing signed and unsigned integers. Then I will assume the input integer is an unsigned 32.

My solution is the following :

#include <stdio.h>
#include <stdint.h>

int main()
{
    uint32_t a = 626;
    uint8_t bytes[4];

    bytes[0] = a & 0xff; //contains Lsb
    bytes[1] = (a >> 8) & 0xff;
    bytes[2] = (a >> 16) & 0xff;
    bytes[3] = (a >> 24) & 0xff; //contains msb

    printf("Bytes: %u, %u, %u, %u\n", bytes[0], bytes[1], bytes[2], bytes[3]);

    uint32_t b = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0];

    printf("Final: %u\n", b);

    return 0;
}

Where as Mischa said. You need to work the result back in something larger than 8 bits. Otherwise you are loosing the bits when shifting more than 8 bits.

Upvotes: 0

Mischa
Mischa

Reputation: 2298

Try using something bigger than uint8_t e.g. uint32_t

Upvotes: 0

Related Questions