The rotary (circular) shift operation is the shifting of the bits of a number by a certain number of positions, with the "dropped" bits wrapping around to the opposite end. In C, there is no built-in operator for this task; this solution is historically related to the portability of the standard library and the necessity to explicitly define behavior for different platforms.
The problem is that the standard shift operators (<<, >>) do not perform a circular shift: they merely shift bits, replacing the "dropped" bits with zeros. To perform a circular shift, one must explicitly combine the results of two shifts and mask the result with a specified number of bits.
The solution is to implement a circular shift manually. For a 32-bit unsigned integer, it looks like this:
uint32_t rotate_left(uint32_t value, unsigned int shift) { return (value << shift) | (value >> (32 - shift)); } uint32_t rotate_right(uint32_t value, unsigned int shift) { return (value >> shift) | (value << (32 - shift)); }
Key points:
Can the << or >> operator perform a circular shift without additional operations?
No. Regular shifts replace bits that go out of bounds with zeros instead of wrapping them around to the other side.
What happens if a shift is performed equal to the size of the type (shift equals the number of bits in the number)?
The behavior is undefined (Undefined Behavior according to the C standard), always perform shifts modulo the size of the type.
Is it safe to perform rotary shifts with these functions for signed types?
No, always use unsigned types, as bitwise shifts for signed types behave differently depending on the compiler and architecture.
Using a regular shift for circular shifting:
uint32_t x = 0xFA3C0F00; uint32_t y = x << 5; // Not circular
Pros:
Cons:
Using a manual rotary shift function considering type size and protecting against UB:
uint32_t x = 0xFA3C0F00; uint32_t y = rotate_left(x, 5);
Pros:
Cons: