Why is there a >>> op

What is the difference between >> and >>>? I’v heard they are the 'right shift' op and the 'shift right zero fill' op, but I don’t get it. Shouldn’t the >> already be zero filled?!? I’m a little scared now..

1
2
3
4
5
6
7
8
 #include <iostream>
 #include <bitset>

 int main(){
   unsigned short i = 32; // 00000000 00100000
   std::cout << std::bitset::bitset( (i >> 4) ); // ???????? ??????10 what’s happening??
   std::cout << std::bitset::bitset( (i >> 4) ); // 00000000 00000010 It’s ok... I think. This is what’s, happening right?
 }


Edit: 🤦‍♂️ I just tried to use code tags in the title.
Last edited on
There is no >>> in C++. It's from Java.
With the >> shift operator in C++, it is up to the implementation whether it shifts in a zero or whether it repeats the sign bit (which may of course be 1).
Last edited on
Oh no... this is literally making me wonky ahh!!! I thought they just always zero filled!! Oh well. Thanks! :)
There are two kinds of right-shifts in a CPU: logical and arithmetic. A logical shift always shifts in a zero bit. An arithmetic shift always shift in a copy of the sign bit. Which type of shift >> represents is implementation dependent. Java added the >>> operator to specifically represent a logical shift, so presumably >> is always arithmetic in Java.
>> will do logical shifts when used on unsigned integers. This is the same as what Java's >>> operator does.

>> on signed integers is currently implementation defined for negative values. In C++20 it will be guaranteed to do arithmetic shifts which is the same as Java's >> operator does.

You can test the difference between logical (unsigned) and arithmetic (signed) shifts on this page:
https://onlinetoolz.net/bitshift#base=10&value=32&bits=16&steps=4&dir=r&type=log&allsteps=0
Last edited on
or, bluntly, java needed >>> because java forgot to allow unsigned int types. This operator is used in some languages to limit the size of ints as well, where the type isn't correctly defended (weak typing) against changing behind the scenes, eg if you wanted to shift a 32 bit int but the result is too big so its hidden promoted to 64 bits instead of giving the correct 32 bit truncated result. C++ needs none of this because it is strongly typed and has unsigned types.
Oh oops didn’t notice people were still responding.
@everyone good to know.. kinda relieved because I’m using unsigned.
An arithmetic shift always shift in a copy of the sign bit.
This is incorrect. Arithmetic shift is equivalent to integer division by a power of 2, regardless of how the CPU represents signed integers. For example, in a CPU that represents integers like this:

-16 = 00000
...
-1 = 01111
0 = 10000
1 = 10001
...
15 = 11111

arithmetic shift and bitwise shift would be quite different.
helios wrote:
Arithmetic shift is equivalent to integer division by a power of 2

This is incorrect. :-)
https://en.wikipedia.org/wiki/Arithmetic_shift#Non-equivalence_of_arithmetic_right_shift_and_division

1
2
3
4
5
6
7
#include <iostream>
int main() {
    int a = -1;
    std::cout << (a >> 1) << '\n';   // prints -1
    std::cout << (a / 2)  << '\n';   // prints  0
    return 0;
}

Still, point taken. But the only common place I know of that uses the "biased" representation is in floating point exponents (for some reason).


jonin wrote:
or, bluntly, java needed >>> because java forgot to allow unsigned int types.

Well, that's interesting!

We should make it very clear that in C++ (and C) right-shifts should probably only be used with unsigned integers (or possibly positive values of signed integers).
Last edited on
This is exactly why I never do bitwise operations on signed values. :-)
We should make it very clear that in C++ (and C) right-shifts should probably only be used with unsigned integers (or possibly positive values of signed integers).

It depends on what its for. If its something like a CRC32 algorithm, you just say (unsigned int)(variable) >> n; and its fine because you are just making a binary soup of the bit anyway, the result isn't of much numerical use, the actual value has no meaning apart from 'does it match a previous result of same data' or 'can I repair damaged bit with it' type questions.

If its something where you were dividing by a power of 2, it matters a whole lot.
Topic archived. No new replies allowed.