Convert large number (int) to 4 bytes

Dear members!

I want to convert a large number (int) to 4 bytes. I have a code which works for 2 bytes as an example the number DEC 12345, HEX 3039 uses 2 bytes BIN 0011 0000 0011 1001. The output on "Serial.print" is:

bytes_array[0] = 39
bytes_array[1] = 30
bytes_array[2] = 0
bytes_array[3] = 0
bytes_array[4] = CE

When I tried with this number DEC 123456, HEX 1 E240 which uses 2.5 bytes the output were:

bytes_array[0] = 40
bytes_array[1] = E2
bytes_array[2] = FF
bytes_array[3] = FF
bytes_array[4] = CE

Is there someone who can help me to fix that?
Thanks in advance!

Here is the code so far:

void int2Bytes(uint32_t val, uint8_t* bytes_array){
  int my_int = 12345;
  // Create union of shared memory space
  union {
    uint32_t unit_variable;
    uint8_t temp_array[4];
  } u;
  // Overite bytes of union with in variable
  u.unit_variable = val;
  // Assign bytes to input array
  memcpy(bytes_array, u.temp_array, 4);
  Serial.print("bytes_array[0] = ");
  Serial.println(bytes_array[0],HEX);
  Serial.print("bytes_array[1] = ");
  Serial.println(bytes_array[1],HEX);
  Serial.print("bytes_array[2] = ");
  Serial.println(bytes_array[2],HEX);
  Serial.print("bytes_array[3] = ");
  Serial.println(bytes_array[3],HEX);
  Serial.print("bytes_array[4] = ");
  Serial.println(bytes_array[4],HEX);

}

12345 != 123456

And 123456 doesn't fit in a sixteen bit int.

Hi,

For testing, I am changing the number manually. Yes, that number will not feet on 16 bits (see attached file) Therefore I need 4 bytes for being able to convert bigger numbers than 123456. But the code works for 12345 which uses 2 bytes.

BR

123456.PNG

The union you're using is completely unnecessary, and even worse, it actually makes your program invalid. Using unions for type punning is not allowed in C++.

The reason it's not working, is because you are saving 123456 as an int, which is only 16 bits wide on most basic Arduinos. 123456 does not fit an int, because log2(123456) = 16.9 > (16 - 1).
123456 overflows to a negative number, so when you later convert it to a 32-bit integer, it is sign extended, and the two most significant bytes are all ones (0xFFFF).

Finally, you're accessing beyond the bounds of your array. bytes_array[4] is not an element of the array if the array is of size 4.

You can add the number of elements to the signature of the function so the compiler can give an error if you try to use an array of the incorrect size.

[color=#00979c]void[/color] [color=#000000]int2Bytes[/color][color=#000000]([/color][color=#00979c]uint32_t[/color] [color=#000000]val[/color][color=#434f54],[/color] [color=#00979c]uint8_t[/color] [color=#000000]([/color][color=#434f54]&[/color][color=#000000]bytes_array[/color][color=#000000])[/color][color=#000000][[/color][color=#000000]4[/color][color=#000000]][/color][color=#000000])[/color] [color=#000000]{[/color]
  [color=#d35400]memcpy[/color][color=#000000]([/color][color=#000000]bytes_array[/color][color=#434f54],[/color] [color=#434f54]&[/color][color=#000000]val[/color][color=#434f54],[/color] [color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]val[/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#00979c]static_assert[/color][color=#000000]([/color][color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]val[/color][color=#000000])[/color] [color=#434f54]==[/color] [color=#000000]4[/color][color=#434f54],[/color] [color=#005c5f]"Error: uint32_t expected to be 4 bytes"[/color][color=#000000])[/color][color=#000000];[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#005c5f]"bytes_array[0] = "[/color][color=#000000])[/color][color=#434f54],[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]bytes_array[/color][color=#000000][[/color][color=#000000]0[/color][color=#000000]][/color][color=#434f54],[/color] [color=#00979c]HEX[/color][color=#000000])[/color][color=#000000];[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#005c5f]"bytes_array[1] = "[/color][color=#000000])[/color][color=#434f54],[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]bytes_array[/color][color=#000000][[/color][color=#000000]1[/color][color=#000000]][/color][color=#434f54],[/color] [color=#00979c]HEX[/color][color=#000000])[/color][color=#000000];[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#005c5f]"bytes_array[2] = "[/color][color=#000000])[/color][color=#434f54],[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]bytes_array[/color][color=#000000][[/color][color=#000000]2[/color][color=#000000]][/color][color=#434f54],[/color] [color=#00979c]HEX[/color][color=#000000])[/color][color=#000000];[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]print[/color][color=#000000]([/color][color=#005c5f]"bytes_array[3] = "[/color][color=#000000])[/color][color=#434f54],[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]println[/color][color=#000000]([/color][color=#000000]bytes_array[/color][color=#000000][[/color][color=#000000]3[/color][color=#000000]][/color][color=#434f54],[/color] [color=#00979c]HEX[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000]115200[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#5e6d03]while[/color] [color=#000000]([/color][color=#434f54]![/color][b][color=#d35400]Serial[/color][/b][color=#000000])[/color][color=#000000];[/color]
  [color=#00979c]uint8_t[/color] [color=#000000]bytes[/color][color=#000000][[/color][color=#000000]4[/color][color=#000000]][/color][color=#000000];[/color]
  [color=#000000]int2Bytes[/color][color=#000000]([/color][color=#000000]12345[/color][color=#434f54],[/color] [color=#000000]bytes[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]int2Bytes[/color][color=#000000]([/color][color=#000000]123456[/color][color=#434f54],[/color] [color=#000000]bytes[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color][color=#000000]}[/color]

Pieter

Your binary displays does not show leading zeros, try it with a large negative number like -1564384201.

Hi,

I tried the code above and the output was :

bytes_array[0] = 40
bytes_array[1] = E2
bytes_array[2] = FF
bytes_array[3] = FF

and should be:

bytes_array[0] = 40
bytes_array[1] = E2
bytes_array[2] = 01
bytes_array[3] = 00

Tonyboy:
Hi,

I tried the code above and the output was :

bytes_array[0] = 40
bytes_array[1] = E2
bytes_array[2] = FF
bytes_array[3] = FF

and should be:

bytes_array[0] = 40
bytes_array[1] = E2
bytes_array[2] = 01
bytes_array[3] = 00

Works perfectly for me.

Hi,

Yes, but when I am using int2Bytes(my_int, bytes); instead int2Bytes(123456, bytes); like:

 uint8_t bytes[4];
 int my_int = 123456;
 int2Bytes(my_int, bytes);

the output is:

bytes_array[0] = 40
bytes_array[1] = E2
bytes_array[2] = FF
bytes_array[3] = FF

That is because I will have an integer which will be converted to bytes to be able to build CAN message.
This function works perfectly for integers which use 2 bytes:

void CAN_Write() {
  MCP2515 mcp2515(CS_CAN_PIN);
  SPI.begin();//----------Start CAN------------------------
  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS, MCP_8MHZ);
  mcp2515.setNormalMode();
  
  struct can_frame frame1;//Message nr1
  frame1.can_id = 0x100;
  frame1.can_dlc = 4;
  frame1.data[0] = 0x00;
  int my_int = 123456;
  int2Bytes(my_int,&frame1.data[0]);
  mcp2515.sendMessage(&frame1);
  digitalWrite(CS_CAN_PIN, HIGH);
  SPI.end();
}

Tonyboy:

 uint8_t bytes[4];

int my_int = 123456;
int2Bytes(my_int, bytes);

PieterP:
The reason it's not working, is because you are saving 123456 as an int, which is only 16 bits wide on most basic Arduinos. 123456 does not fit an int, because log2(123456) = 16.9 > (16 - 1).
123456 overflows to a negative number, so when you later convert it to a 32-bit integer, it is sign extended, and the two most significant bytes are all ones (0xFFFF).

int my_int = 123456;

123456 doesn't fit into 16 bits.

This has already been pointed-out.

Yes, therefore I want to fix that to be able to send 4 bytes or 32 bits threw CAN as 1 message

Tonyboy:
Yes, therefore I want to fix that to be able to send 4 bytes or 32 bits threw CAN as 1 message

So, don't use a sixteen bit int.

Thank you all for your time!

BR Anton

Hello,

I tried with long instead of int and it worked perfectly :slight_smile:
Thanks!

BR

The correct type to use for 4 bytes is not long, but uint32_t, as demonstrated by the code I posted earlier.