I am trying to convert 4 bytes to an integer using C++.
This is my code:
int buffToInteger(char * buffer)
{
int a = (int)(buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]);
return a;
}
The code above works in almost all cases, for example:
When my buffer is: "[\x00, \x00, \x40, \x00]"
the code will return 16384
as expected.
But when the buffer is filled with: "[\x00, \x00, \x3e, \xe3]"
, the code won't work as expected and will return "ffffffe1"
.
Does anyone know why this happens?
Originally Answered: Is the size of C "int" 2 bytes or 4 bytes? The size of an int is really compiler dependent. Back in the day, when processors were 16 bit, an int was 2 bytes. Nowadays, it's most often 4 bytes on a 32-bit as well as 64-bit systems.
On 16-bit systems (like in arduino), int takes up 2 bytes while on 32-bit systems, int takes 4 bytes since 32-bit=4bytes but even on 64-bit systems, int occupies 4 bytes.
The fact that an int uses a fixed number of bytes (such as 4) is a compiler/CPU efficiency and limitation, designed to make common integer operations fast and efficient.
Your buffer
contains signed characters. So, actually, buffer[0] == -29
, which upon conversion to int
gets sign-extended to 0xffffffe3
, and in turn (0x3e << 8) | 0xffffffe3 == 0xffffffe3
.
You need ensure your individual buffer
bytes are interpreted unsigned
, either by declaring buffer
as unsigned char *
, or by explicitly casting:
int a = int((unsigned char)(buffer[0]) << 24 |
(unsigned char)(buffer[1]) << 16 |
(unsigned char)(buffer[2]) << 8 |
(unsigned char)(buffer[3]));
In the expression buffer[0] << 24
the value 24 is an int
, so buffer[0]
will also be converted to an int
before the shift is performed.
On your system a char
is apparently signed, and will then be sign extended when converted to int
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With