Converting two 8-bit values to one 16-bit value in C

This is a follow-up to an earlier article I wrote about converting 8-bit values to 16-bit values.

There are several common ways to convert two byte *8-bit) values into one word (16-bit) value in C. Here are the ones I see often:

Math

This is how we learned to do it in BASIC. “C = A * 256 + B”:

uint8_t byte1;
uint8_t byte2;
uint16_t word;

byte1 = 0x12;
byte2 = 0x32;

word = byte1 * 256 + byte2;

Bit Shifting

This way generally makes less code, making use of the processor’s ability to bit shift and perform an OR.

word = (byte1 << 8) | byte2;

Unions

union {
   // First union element contains two bytes.
   struct {
      uint8_t byte1;
      uint8_t byte2;
   } Bytes;
   // Second union element is a 16-bit value.
   uint16_t word;
} MyUnion;

MyUnion.Bytes.byte1 = byte1;
MyUnion.Bytes.byte2 = byte2;

That one looks like much more source code but it may generate the smallest amount of executable instructions.

Array Access

And here was one I found at a previous job, which I hadn’t seen before, and haven’t seen since:

uint8_t  bytes[2];
uint16_t value;

value = 0x1234;

bytes[0] = *((uint8_t*)&(value)+1); //high byte (0x12)
bytes[1] = *((uint8_t*)&(value)+0); //low byte  (0x34)

That example is backwards from the topic of this post, but hopefully you can see the approach.

The question today is … which would you choose?

Clean Code would say writing it out in the simplest form is the best, since it would take less time for someone to understand what it was doing. But if you needed every last byte of code space, or every last clock cycle, you might want to do something else.

Which do you think is smallest?

Which do you think is fastest?

Which do you think is easiest to understand?

Comments appreciated.

Until next time…

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.