How to convert an int to two bytes in C/C++?

Asked

Viewed 6,387 times

20

I receive data from a temperature sensor on a microcontroller that has a 10-bit AD converter. I store the data in a variable of type int (32-bit), and I need to send that data via serial communication. To do this, I need to convert that value int for the guy byte, but how to deal with 10 bits if I convert to only one byte I’ll lose information, so I need to convert the int for two bytes so that I can transmit one byte at a time through the serial port. I will also need to convert these two bytes in an integer value again.

How do I convert a int in two bytes and two bytes in a int again, using C/C++?

  • Try to be a little more explicit. When you say int you mean 32 bits? And when it says convert to 2 bytes it is to convert to a short int of 16 bits?

  • 1

    I made some edits in my question. But the int is 32 bits and the two bytes are separated, because I need to byte by byte by serial port.

  • int on the most modern platforms has 4 bytes. And 4 bytes do not fit within 2 bytes, unfortunately. But if you are talking about short int there yes to divide it into separate bytes. ;D

  • The AD converter stores the information in 10 bits. I am storing it in an int of 32, but it could be stored in a short. But the most significant part is all zeroed since the values go from 0 to 1023 only. However, I cannot send an int, I need to send the data byte by byte, so I need to divide this int into 2 bytes (with the least significant part) where the values from 0 to 1023 will be.

  • @Avelino If you need to do the reverse operation, let me know that I update the response.

4 answers

21


One thing we have to clear up first is that the guy int on the modern platforms has 4 bytes. That’s a problem because it is impossible to make 4 bytes fit within 2 bytes, it’s not true?!

On the other hand, there is the ensures that the type short int occupies at least 2 bytes on any platform. These statements can be easily verified by sizeof(), which returns the amount of bytes that a given data type occupies:

printf("%d\n", sizeof(int));
printf("%d\n", sizeof(short int));

This way, this answer assumes that you would like to separate each byte from a variable short int.

To accomplish this task, we can use a bit mask, which involves the application of binary logic (bitwise Operations) and bit displacement (bit shift) to extract the 8 bits that interest us from the original variable.

To begin this task, we declare and initialize an appropriate variable:

short int num = 42345;

It is interesting to note that the number 42345 on the decimal basis is represented by 1010 0101 0110 1001 in the binary base system. It is relevant to know this because after the separation occurs, we will have a variable unsigned char to store the first byte --> 0110 1001 (105), and another variable unsigned char to store the second byte --> 1010 0101 (165).

To extract the first byte of num:

unsigned char byte1 = (num & 255);          // Ou: (num & 0xFF)
printf("%d\n\n", byte1);

To extract the second byte of num:

unsigned char byte2 = ((num >> 8) & 255);   // Ou: ((num >> 8) & 0xFF);
printf("%d\n", byte2);

The purpose of the answer is not to discuss how bit masks work, but to demonstrate how the problem could be solved in this way. There are over a hundred programming books and many more online records that describe in detail the operation of bit masks.

Good luck!

  • There is no guarantee that short at all times will have 2 bytes. This is true, however, on any platform I’ve heard of. Another point: the & 255 is unnecessary since conversion to unsigned char will already know it. Still it is good to maintain by legibility.

  • Hello, thank you. Could you point out a reference that says short int no 16 bits in the C language?

  • 1

    Standard C11 (N1570), section 5.2.4.2.1 "Sizes of integer types": "The values Given Below Shall be replaced by Constant Expressions suitable for use in #if preprocessing Directives. [...] Their implementation-defined values Shall be Equal or Greater in magnitude (Absolute value) to those Shown, with the same Sign. [...] Maximum value for an Object of type unsigned short int USHRT_MAX 65535" unsigned short int must have at least 2 bytes. But it may have more. There is no limitation anywhere.

  • 1

    I read the section, thank you. I will adjust the explanation in the reply :)

12

Convert valor in 2 bytes:

byte[0] = valor / 256;
byte[1] = valor % 256;

Convert two bytes

valor = byte[0] * 256 + byte[1];

This for Big Endian, if you prefer Little Endian, swap the bytes

  • Could you explain to me how this code works? It’s unclear to me.

  • What is your doubt of the code? Are the operations (/, %, *)?

  • What is the magic behind this? The math part... I don’t understand how these operations are responsible for making the conversion.

  • 2

    Let’s say you’re worth 1023 (1111111111 in binary). 1023 / 256 of the 3 and 255 rest; ie will 3 (11) for the first byte and 255 (11111111) to the other

  • 1

    Wouldn’t division operations be heavier than just shift? in case it suggests is on a microcontroller since it uses an AD Converter, so it is important to be cautious with certain choices.

  • In fact, since using power values of 2, shifts and bitwise-ands would result in superior performance.

  • In principle the compiler will do these direct optimizations. I prefer to see a / 256 than a >> 8 or a % 256 than a & 0xff.

Show 2 more comments

9

You can use union to do this kind of operation.

Thus:

union Valor
{
    uint32_t dword;

    struct
    {
        uint32_t valor;
    };

    struct
    {
        uint16_t word0;
        uint16_t word1;
    };

    struct
    {
        uint8_t byte0;
        uint8_t byte1;
        uint8_t byte2;
        uint8_t byte3;
    };
};

But, check if the compiler supports this before. I say this because it has too much compiler for very limited microcontroller. The variables uint32_t, uint16_t and uint8_t may have another name depending on the compiler (version, platform, etc.), but are usually defined in #include <stdint.h>.

Int for 2 bytes

Then you wear it like this:

Valor var;
var.valor = 700;

printf("Valor = %d\n", var.valor);
printf("Byte 0 = %d\n", var.byte0);
printf("Byte 1 = %d\n", var.byte1);
printf("Word 0 = %d\n", var.word0);

As you want 2 bytes, you want the word0 (to Big Endian).

Can also be:

uint32_t variavel_qualquer = 700;
Valor* var = (Valor*) &variavel_qualquer;
printf("Word 0 = %d\n", var->word0);

2 bytes for Int

Valor var;
var.valor = 0; // Para garantir que estará tudo zero.

var.byte0 = 188;
var.byte1 = 2;

printf("Resultado = %d", var.valor); // Retorna 700

In Ideone: http://ideone.com/9e69z6

1

The simplest way is to use Shift and Bit-Wise operators, mainly because it is easily mapped to an instruction Assembly and how we are in a context of microcontroller it is essential that we have the most optimal code possible.

int orig = 0x0403;
byte dest[4];

// para converter de inteiro para byte
dest[0] = orig         & 0xff;
dest[1] = (orig >> 8)  & 0xff; 
dest[2] = (orig >> 16)  & 0xff; 
dest[3] = (orig >> 24)  & 0xff; 

// para retornar os dois byte para um inteiro
orig = (dest[3] << 24) + (dest[2] << 16) + (dest[1] << 8) + dest[0]

Browser other questions tagged

You are not signed in. Login or sign up in order to post.