I'd like to move an integer up to the nearest 'divisible by 4' number in C++, but not if the number is currently divisible by 4. Here's my best attempt, but I'm sure this is suboptimal:
offset = (offset & 3) ? (offset | 3) +1 : offset;
There must surely be a fast way of doing this that doesn't include the tertiary IF statement?
Additional note: In this case offset is a 32-bit int.
offset = (offset + 3) & ~(decltype(offset))3;
Or
#include <type_traits>
// ...
offset = (offset + 3) &
~static_cast<std::remove_reference<decltype(offset)>::type>(3);
if you need to support the possibility that offset
is a reference type, such as size_t&
. Thanks @BaummitAugen.
It also seems to work when offset
is wider than int
even without the type cast, offset = (offset + 3) & ~3;
, but I am uncertain as to whether or not it is mandated by the language standard.
This algorithm can be described in English as "add 3 then round down".
The rounding down part is done by setting the two least significant bits to zero by binary arithmetics. Unsetting of bits is done by applying binary AND with the inverse bit pattern, in other words we make a bit pattern of all the bits whose value we want to keep unchanged and apply it as a mask.
Binary representation of 3
: 00000011
We get the inverse bit mask with the ~
(bitwise NOT, not to be confused with !
logical NOT) operator: ~3
For the ~
operator, the size of the operand determines the size of the result, so on my machine ~(unsigned char)3 == 252
(1111 1100
) and ~(unsigned int)3 == 4294967292
(1111 1111 1111 1111 1111 1111 1111 1100
). The default size for an integer literal is int
.
When offset
is a wider type (has more bits) than int
, we need the operand to ~
to be widened so the bitmask matches. This is why we cast the literal 3
to the same type as offset
.
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