I just want to concatenate my uint8_t array to uint64_t. In fact, I solved my problem but need to understand the reason. Here is my code;
uint8_t byte_array[5];
byte_array[0] = 0x41;
byte_array[1] = 0x42;
byte_array[2] = 0x43;
byte_array[3] = 0x44;
byte_array[4] = 0x45;
cout << "index 0: " << byte_array[0] << " index 1: " << byte_array[1] << " index 2: " << byte_array[2] << " index 3: " << byte_array[3] << " index 4: " << byte_array[4] << endl;
/* This does not work */
uint64_t reverse_of_value = (byte_array[0] & 0xff) | ((byte_array[1] & 0xff) << 8) | ((byte_array[2] & 0xff) << 16) | ((byte_array[3] & 0xff) << 24) | ((byte_array[4] & 0xff) << 32);
cout << reverse_of_value << endl;
/* this works fine */
reverse_of_value = (uint64_t)(byte_array[0] & 0xff) | ((uint64_t)(byte_array[1] & 0xff) << 8) | ((uint64_t)(byte_array[2] & 0xff) << 16) | ((uint64_t)(byte_array[3] & 0xff) << 24) | ((uint64_t)(byte_array[4] & 0xff) << 32);
cout << reverse_of_value << endl;
The first output will be "44434245" and second one will be "4544434241" that is what I want.
So as we see when I use casting each byte to uint64_t code works, however, if I do not use casting it gives me irrelevant result. Can anybody explain the reason?
Left-shifting a uint8_t
that many bits isn't necessarily going to work. The left-hand operand will be promoted to int
, whose width you don't know. It could already be 64-bit, but it could be 32-bit or even 16-bit, in which case… where would the result go? There isn't enough room for it! It doesn't matter that your code later puts the result into a uint64_t
: the expression is evaluated in isolation.
You've correctly fixed that in your second version, by converting to uint64_t
before the left-shift takes place. In this situation, the expression will assuredly have the desired behaviour.
Here is an example showing left-shift turning the char to 0. At least it does so on my machine, gcc 4.8.4, Ubuntu 14.04 LTS, x86_64.
#include <iostream>
using std::cout;
int main()
{
unsigned char ch;
ch = 0xFF;
cout << "Char before shift: " << static_cast<int>(ch) << '\n';
ch <<= 10;
cout << "Char after shift: " << static_cast<int>(ch) << '\n';
}
Note also my comment to the original question above, on some platforms, the 0x45 shifted 32 bits actually ends up in the least significant byte of the 64-bit value.
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