Reputation: 12324
If I have a large int, say a uint64_t, and an array of uint8_t, e.g.:
uint64_t large = 12345678901234567890;
uint8_t small[5];
and I want to copy the 8 least significant bits of the uint64_t
into an element of the array of uint8_t
, is it safe to just use:
small[3] = large;
or should I use a bit-mask:
small[3] = large & 255;
i.e. Is there any situation where the rest of the large int may somehow overflow into the other elements of the array?
Upvotes: 8
Views: 2424
Reputation: 303890
This is perfectly safe:
small[3] = large;
and such a conversion is explicitly described in [conv.integral]:
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type).
That is, these four statements all are guaranteed to end up with the same value in small[3]
:
small[3] = large;
small[3] = large % 256;
small[3] = large & 255;
small[3] = static_cast<uint8_t>(large);
there's no functional reason to do the %
or &
or cast yourself, though if you want to anyway I would be surprised if the compiler didn't generate the same code for all four (gcc and clang do).
The one difference would be if you compile with something like -Wconversion
, which would cause this to issue a warning (which can sometimes be beneficial). In that case, you'll want to do the cast.
Upvotes: 3
Reputation: 14860
It will most certainly not cause data to be processed incorrectly. However, some compilers may generate a warning message.
There are two options to avoid these.
You can cast your variable:
(uint8_t)large
Or you can disable the warning:
#pragma warning(disable:4503)
I would suggest casting the variable, because hiding compiler warnings will potentially keep you from spotting actual problems and is therefore not best practice.
Upvotes: 5