I'm reading data from a device that returns a lot of bytes. 5 bytes are representing a big number that I need. For example, I receive 24C9A75A2E and it means the value is 158002010670.
These bytes are in a byte array positions 5 to 9.
I tried converting this number to a long like this:
long long val = 0;
val += (long)dataRx[9] << 32;
val += (long)dataRx[8] << 24;
val += (long)dataRx[7] << 16;
val += (long)dataRx[6] << 8;
val += (long)dataRx[5];
If you had printed in hex it would have made more sense.
2E
5A
A7
C9
24
and
1520945444 = 5AA7C924 hex
So the result is truncated to 4 bytes and the digits are reverse order in 2 byte chunks. Probably due to using the brain dead Intel ordering. (What? Me? have a preference in the big vs little endian war?)
int64_t val = 0;
val += ((int64_t)dataRx[9]) << 32;
val += ((int64_t)dataRx[8]) << 24;
val += ((int64_t)dataRx[7]) << 16;
val += ((int64_t)dataRx[6]) << 8;
val += ((int64_t)dataRx[5]);
The below prints the right answer, you figure it out. I tried everything, so everything is still in there. Translation to Arduino-land an exercise for the reader.
It has nothgin to do with endianess.
# include <stdio.h>
// 24C9A75A2E and it means the value is 158002010670
unsigned char dataRx[10];
int main() {
printf("Jello Whirled!\n\n");
dataRx[9] = 0x2e;
dataRx[8] = 0x5a;
dataRx[7] = 0xa7;
dataRx[6] = 0xc9;
dataRx[5] = 0x24;
long long val = 0;
val |= ((unsigned long long) dataRx[5]) << 32;
printf("1 val = %llx\n", val);
val |= ((unsigned long long) dataRx[6]) << 24;
printf("2 val = %llx\n", val);
val |= ((unsigned long long) dataRx[7]) << 16;
printf("3 val = %llx\n", val);
val |= ((unsigned long long) dataRx[8]) << 8;
printf("4 val = %llx\n", val);
val |= (unsigned long long) dataRx[9];
printf("\n\n");
printf("val = %lld\n", val);
printf("val = %llx\n", val);
}
yields
Jello Whirled!
1 val = 2400000000
2 val = 24c9000000
3 val = 24c9a70000
4 val = 24c9a75a00
val = 158002010670
val = 24c9a75a2e
...Program finished with exit code 0
Press ENTER to exit console.
HTH, time for something else. A pill of some kind, probably.
int64_t val = 0;
val += ((int64_t)dataRx[5]) << 32;
val += ((int64_t)dataRx[6]) << 24;
val += ((int64_t)dataRx[7]) << 16;
val += ((int64_t)dataRx[8]) << 8;
val += ((int64_t)dataRx[9]);
The lesson to be learned? Always use int8_t, uint8_t, etc. Then you'll know signed / unsigned. Use char only for ASCII characters. Those are <= 127 so signed / unsigned doesn't matter.