C - Type - Converting two uint8_t words into one of uint16_t and one of uint16_t into two of uint8_t

Sometimes you need to convert one uint16_t variable into two uint8_t.

As we manipulate binaries, it's impossible to do something like that: 0xAB + 0xCD = 0xABCD.

Indeed, the result of 0xAB + 0xCD = 0x178 because 0xAB = 171 and 0xCD = 205.

So 0xAB + 0xCD = 376 in decimal but 0x178 in hexadecimal.

Furthermore, we cannot add more than 255 value inside a byte, because this is a 8-bit long number.

Let's see how to manipulate uint16_t and uint8_t types in this tutorial with an example.

Explanation

As said previously, we can't add hexadecimal numbers like decimals.

To be more easy, we've then to use the binary shifting.

In the code below we're converting two uint8_t words into a uint16_t one.
By using the "<< 8" we tell the compiler to move data from right to left:

    dataBoth = dataFirst; // dataBoth = 0x00AB

Indeed, 0x00AB = 00000000 10101011 (in binary).
So if we do:

result = 00000000 10101011 << 8

We have:

 result = 10101011 00000000

We have then just to do:

    dataBoth = dataBoth << 8; // dataBoth = 0xAB00

Finally we add 0x00CD to dataBoth with the OR gate:

dataBoth |= dataSecond; // dataBoth = 0xABCD

Because:

  10101011 00000000
+ 00000000 11001101
====================
= 10101011 11001101

And 10101011 11001101 = 0xABCD.

For the second function, we do the same but with the AND gate.
And we use a pointer on uint8_t to retrieve the two values.

I use two ways to add data and get them, one with the value at a certain memory address and one with the first element of an array.

Notice that they are exactly the same, indeed:

*(arrayData) = arrayData[0]
*(++arrayData) = arrayData[1]

Code

#include <time.h>
#include <stdio.h>

uint16_t convertFrom8To16(uint8_t dataFirst, uint8_t dataSecond) {
    uint16_t dataBoth = 0x0000;

    dataBoth = dataFirst;
    dataBoth = dataBoth << 8;
    dataBoth |= dataSecond;
    return dataBoth;
}

uint8_t *convertFrom16To8(uint16_t dataAll) {
    static uint8_t arrayData[2] = { 0x00, 0x00 };

    *(arrayData) = (dataAll >> 8) & 0x00FF;
    arrayData[1] = dataAll & 0x00FF;
    return arrayData;
}

int main() {
    uint8_t *dataMix;
    uint8_t data1 = 0xAB;
    uint8_t data2 = 0xCD;
    uint16_t data3 = 0x0000;

    data3 = convertFrom8To16(data1, data2);
    printf("data1 = %04X\n", data1);
    printf("data2 = %04X\n", data2);
    printf("data3 = %04X\n", data3);

    dataMix = convertFrom16To8(data3);
    printf("dataMix[0] = %02X\n", dataMix[0]);
    printf("(++dataMix) = %02X\n", *(++dataMix));
    return 0;
}

Result

data1 = 00AB
data2 = 00CD
data3 = ABCD
dataMix[0] = AB
(++dataMix) = CD

Conclusion

An exercise not so easy to understand.

But as always, well done, you've made it. heart

Comments

Comment: 

uint8_t
uint8_t
uint8_t
uint16_t

In all these types, that does the _t stands for?

Comment: 

Hello Tanmay,

The "_t" suffix simply stands for "type" laugh

Add new comment

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.