0

From an assembly book:

Another set of logical operations which apply to bit strings are the shift and rotate operations. These two categories can be further broken down into left shifts, left rotates, right shifts, and right rotates. These operations turn out to be extremely useful to assembly language programmers.

and:

Another pair of useful operations are rotate left and rotate right. These operations behave like the shift left and shift right operations with one major difference: the bit shifted out from one end is shifted back in at the other end.

Are their rotate operations in C that are equivalent to the rotate operations in assembly?

  • [tag:c] only has shift bitwise operator. No rotate is provided. Take a look at [available operators](https://en.wikipedia.org/wiki/Bitwise_operations_in_C) – LPs May 02 '16 at 15:42
  • 2
    See this [post](http://stackoverflow.com/questions/13099406/why-doesnt-c-have-rotate-left-right-operators) – terence hill May 02 '16 at 15:42
  • 1
    And also this [answer](http://stackoverflow.com/questions/776508/best-practices-for-circular-shift-rotate-operations-in-c) for a correct implementation – terence hill May 02 '16 at 15:56

2 Answers2

6

Although C has no counterpart for rotation bit shifts of assembly, you can certainly implement them yourself by OR-ing the highest / lowest bit of the original number into the result of a regular shift.

Here is an example for unsigned 32-bit integers:

uint32_t val = ... // This is the value being rotated
uint32_t rol = (val << 1) | (val >> 31);
uint32_t ror = (val >> 1) | (val << 31);

You can generalize this to rotate by any number of bits, as follows:

uint32_t val = ... // This is the value being rotated
uint32_t n = ... 
n &= 31;           // Force n into the range of 0..31, inclusive
uint32_t rol = (val << n) | (val >> (-n & 31));
uint32_t ror = (val >> n) | (val << (-n & 31));

Using an unsigned type is important, because otherwise right shifts would sign-extend the value, producing incorrect results for values that have their sign bit set to 1.

Thanks Jester and Olaf for the ideas on improving and generalizing this to n shifts by n bits.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 2
    Are these patterns recognised by common compilers (gcc, clang, msvc(++) ) as rotate and typically replaced by the corresponding CPU instruction? – too honest for this site May 02 '16 at 15:47
  • Oh, and I did not DV! – too honest for this site May 02 '16 at 15:47
  • @Jester: Feel free to provide a betteranswer. The code looks fine to me. – too honest for this site May 02 '16 at 15:48
  • I didn't DV either. According to godbolt check, at least on x86 gcc and clang understand these but icc doesn't. In any case I find the pure shifting version more readable. – Jester May 02 '16 at 15:48
  • …@Jester: Yes, it is. I'm just not sure which one will be optimised. Anyway, your version has the advantage to support more than rotating by a single bit. – too honest for this site May 02 '16 at 15:51
  • 1
    You might want to put in a note to always use unsigned types for this, as the signed shifts will be implementation-defined or undefined frequently. – EOF May 02 '16 at 15:56
  • Your rotate-by-`n` expressions have possible undefined-behaviour. See http://stackoverflow.com/a/776523/224132 for best-practices. The code there compiles with no overhead even with [`gcc -O3 -fsanitize=undefined`](https://godbolt.org/g/gfblZw), but yours has lots of checks. – Peter Cordes May 02 '16 at 18:38
  • My bad; if you already limit n to that range, you're safe from undefined behaviour. It is possible to implement `uint32_t rotl32(uint32_t val, unsigned n)` with no undefined behaviour for any `n`, with code that compiles to just one machine instruction. If you do the range-limiting the same way the x86 instruction does, the compiler can use it directly. Downvoted for not showing that part, because getting that right is the key to an efficient rotate wrapper function that doesn't turn into branches or `and`s in the compiler output. – Peter Cordes May 02 '16 at 19:03
  • 1
    @dasblinkenlight - To avoid undefined behavior, I think Peter Cordes was referring to `rol = (val << n) | (val >> (-n & 31));`, or, more generally: `rol = (val << n) | (val >> (-n & (CHAR_BIT*sizeof(val)-1)));`. And likewise for rotate right. See [this page on Wikipedia](https://en.wikipedia.org/wiki/Circular_shift). – owacoder May 02 '16 at 19:24
  • @owacoder: yes, exactly. That's John Regehr's code that I put in the FAQ question and on Wikipedia back when I updated the Q&A I linked to. – Peter Cordes May 02 '16 at 19:26
  • @Olaf I've observed `gcc` emit rotate instructions for constant numbers of bits, that is code similar to the first examples. Have never tried with a variable. – Gene Aug 13 '17 at 03:18
  • @Olaf Actually just tried gcc v7.1, and it does fine with the variable form, too with -O1 optimization. – Gene Aug 13 '17 at 03:23
2

In addition to the other answer: the Microsoft compiler has intrinsics that generate CPU-level rotation instructions: _rotl16, _rotr16, etc. Those are CPU dependent, naturally.

Recent versions of GCC have _rotr, _rotl, too.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • Is there anything like that in GCC also? – harold May 02 '16 at 16:15
  • See if _rotr , _rotl are available in your version of GCC. Those are recent additions, it seems. – Seva Alekseyev May 02 '16 at 16:26
  • @harold: I checked the gcc manual and didn't see any rotate builtins. It does recognize the standard idiom for rotates, and with careful coding you can write a rotate that has no undefined behaviour but still compiles to just a single machine instruction (no branching or `and` instructions). http://stackoverflow.com/questions/776508/best-practices-for-circular-shift-rotate-operations-in-c – Peter Cordes May 02 '16 at 18:42