arrayscpointersendianness

C convert 2 sequential uint8_t to one uint16_t


My goal is to convert an array that has two uint8_t to one unint16_t.

int main() {
    uint8_t bytes[] = {0, 126};
    uint8_t *pointer = bytes;
    printf("Hex: %x", (*(uint16_t*)pointer));
}

output

Hex: 7e00                                                                                                                 

Why is output 7e00 ?

shouldn't the bytes array look like this in memory 0x00 0x7e ?
and when telling C to cast pointer to uint16_t* and print what it's pointing to I expect it to print 007e.
But that wasn't the case!


Solution

  • shouldn't the bytes array look like this in memory 0x00 0x7e ?

    The way the order of bytes in memory are interpreted as a uint16_t depends on the Endianness of your system.

    Also *(uint16_t*)pointer) invokes undefined-behavior since the pointer does not hold an address of a valid uint16_t. This means the standard gives no guarantee for the output of the program.

    My goal is to convert an array that has two uint8_t to one unint16_t

    As commented above you can use a combination of bit shifts and bit-wise ORs to achieve that:

    uint16_t value = (uint16_t)bytes[0] << 8 | (uint16_t)bytes[1];
    

    Note that as @Lundin commented below, the cast of the first byte to uint16_t is required for conforming with systems where int is 16 bit (although it's not very common). The cast of the second byte is not strictly required, but here to avoid an implicit conversion.

    Live demo