Why should I overlay `uint8_t` with` uint64_t` * before * moving it to the left?

I just want to combine my uint8_t array with uint64_t. In fact, I solved my problem, but I 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 the second will be "4544434241", which I want.

Thus, as we see, when I use casting of each byte for the uint64_t code, however, if I do not use casting, this gives me an irrelevant result. Can anyone explain the reason?

+5
source share
3 answers

The left offset is a uint8_t that many bits will not necessarily work. The left operand will be assigned the value int , the width of which you do not know. It may already be 64-bit, but it may be 32-bit or even 16-bit, in this case & hellip; where will the result be? Not enough space for this! It doesn't matter that your code later puts the result in uint64_t : the expression is evaluated in isolation.

You correctly fixed this in the second version by switching to uint64_t before the left shift. In this situation, the expression will undoubtedly have the desired behavior.

+6
source

Here is an example showing a left shift turning char into 0. At least it does this 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'; } 

Pay attention also to my comment on the original question above, on some platforms, 32 bits shifted to 0x45 actually end in the low byte value of the 64-bit value.

+2
source

Changing a type by more than the number of bits in a type is undefined behavior in C ++. See this answer for more details: fooobar.com/questions/108009 / ...

+1
source

All Articles