P: n/a

Noticed something odd in the way bit shifting was working today.
As far as I have ever heard, shifting will shift in zeros(signed ints
aside)
However I foudn something odd when I am shifting exactly the number of
bits in a value... i.e.
uint32_t x = 5;
uint32_t y = x << 32;
uint32_t z = x << 32;
In the above example y and z are both still 5. Why is this?
Now I understand doing a shift like this seems silly, but in this code
sometimes the resulting shift validly turns out to be exactly the
number of bits in that data type, and expects the result to be 0.
I can change the code to handle this special case... I was just
wondering why this was happening..  
Share this Question
P: n/a

GGG wrote: Noticed something odd in the way bit shifting was working today.
As far as I have ever heard, shifting will shift in zeros(signed ints aside)
However I foudn something odd when I am shifting exactly the number of bits in a value... i.e.
uint32_t x = 5; uint32_t y = x << 32; uint32_t z = x << 32;
In the above example y and z are both still 5. Why is this?
Now I understand doing a shift like this seems silly, but in this code sometimes the resulting shift validly turns out to be exactly the number of bits in that data type, and expects the result to be 0.
I can change the code to handle this special case... I was just wondering why this was happening..
It shifts the number of bits determined from the right operand by
taking the remainder from dividing by the number of total bits in
the left operand. Take 32, divide by 32, take the remainder, you
get 0. That's the number of bits shifted to the left. IOW, none.
If you do
uint32_t x = 5;
uint32_t y = x << 33;
you will have y == (uint32_t)10 (most likely, given common meaning
of 'uint32_t').
V  
P: n/a

Victor Bazarov 20040526 : GGG wrote: Noticed something odd in the way bit shifting was working today.
As far as I have ever heard, shifting will shift in zeros(signed ints aside)
However I foudn something odd when I am shifting exactly the number of bits in a value... i.e.
uint32_t x = 5; uint32_t y = x << 32; uint32_t z = x << 32;
In the above example y and z are both still 5. Why is this?
Now I understand doing a shift like this seems silly, but in this code sometimes the resulting shift validly turns out to be exactly the number of bits in that data type, and expects the result to be 0.
I can change the code to handle this special case... I was just wondering why this was happening..
It shifts the number of bits determined from the right operand by taking the remainder from dividing by the number of total bits in the left operand. Take 32, divide by 32, take the remainder, you get 0. That's the number of bits shifted to the left. IOW, none.
If you do
uint32_t x = 5; uint32_t y = x << 33;
you will have y == (uint32_t)10 (most likely, given common meaning of 'uint32_t').
Exactly, and the reason is simple: most hardware simply takes as many bits
from the shift value as needed, ignoring the higher valued bits.
In the case of uint32_t, 5 bits. In other words,
uint32_t(x) << y == uint32_t(x) << (y & 31)
Walter Tross  
P: n/a

"GGG" schrieb uint32_t x = 5; uint32_t y = x << 32; uint32_t z = x << 32; In the above example y and z are both still 5. Why is this? Now I understand doing a shift like this seems silly, but in this code sometimes the resulting shift validly turns out to be exactly the number of bits in that data type, and expects the result to be 0.
It doesn't matter what you are expecting. The behaviour of shifts defined only if the value of the right operand is less than the number of bits in the left operand. So shifting a 32bit value by 32 or more is undefined or at least not specified in the standard and each compiler may do whatever it thinks to be best.
Heinz  
P: n/a

Ah... I figured out what was really going on here.
I originally got no compiler warnings from my real program, as the
value I was shifting by was a variable.
I should have payed better attention to my little test program.
uint32_t x = 1 << 32;
//here, x is still 1. Shift any 32 bit int by 32 bits and it stays the
exact same number
That gives a compiler warning because I am shifting by the size of the
data type. The problem here is that it is really just multiplying by
2^32. So... it stays that same. So in reality, shifting doesn't really
"shift in zeros", it does multipication, making it look like it shifts
in zeros. This only becomes apparent when I am shifting by the actual
data type size.
So simply put, if you shift any integer by the number of bits in its
data type, its going to be the exact same number.
Shifting an 8 bit int by 8 bits is NOT 0, it is the same number.
Shifting an 32 bit int by 32 bits is NOT 0, it is the same number.
Kind of interesting I think...  
P: n/a

GGG wrote: Ah... I figured out what was really going on here.
I originally got no compiler warnings from my real program, as the value I was shifting by was a variable.
I should have payed better attention to my little test program.
uint32_t x = 1 << 32; //here, x is still 1. Shift any 32 bit int by 32 bits and it stays the exact same number
That gives a compiler warning because I am shifting by the size of the data type. The problem here is that it is really just multiplying by 2^32. So... it stays that same. So in reality, shifting doesn't really "shift in zeros", it does multipication, making it look like it shifts in zeros. This only becomes apparent when I am shifting by the actual data type size.
So simply put, if you shift any integer by the number of bits in its data type, its going to be the exact same number.
Shifting an 8 bit int by 8 bits is NOT 0, it is the same number. Shifting an 32 bit int by 32 bits is NOT 0, it is the same number.
Kind of interesting I think...
You're wrong. Read Heinz's post.  
P: n/a

Jeff Schwab wrote: GGG wrote:
Ah... I figured out what was really going on here.
I originally got no compiler warnings from my real program, as the value I was shifting by was a variable.
I should have payed better attention to my little test program.
uint32_t x = 1 << 32; //here, x is still 1. Shift any 32 bit int by 32 bits and it stays the exact same number
That gives a compiler warning because I am shifting by the size of the data type. The problem here is that it is really just multiplying by 2^32. So... it stays that same. So in reality, shifting doesn't really "shift in zeros", it does multipication, making it look like it shifts in zeros. This only becomes apparent when I am shifting by the actual data type size.
So simply put, if you shift any integer by the number of bits in its data type, its going to be the exact same number.
Shifting an 8 bit int by 8 bits is NOT 0, it is the same number. Shifting an 32 bit int by 32 bits is NOT 0, it is the same number.
Kind of interesting I think...
You're wrong. Read Heinz's post.
Better yet, read the first part of section 5.8 of the ISO/IEC 14882:2003
standard:
The behavior is undefined if the right operand is negative,
or greater than or equal to the length in bits of the
promoted left operand.  
P: n/a

On Wed, 26 May 2004 22:42:52 +0200, "Heinz Ozwirk" <wa******@gmx.de>
wrote in comp.lang.c++: "GGG" schrieb
uint32_t x = 5; uint32_t y = x << 32; uint32_t z = x << 32;
In the above example y and z are both still 5. Why is this?
Now I understand doing a shift like this seems silly, but in this code sometimes the resulting shift validly turns out to be exactly the number of bits in that data type, and expects the result to be 0.
It doesn't matter what you are expecting. The behaviour of shifts defined only if the value of the right operand is less than the number of bits in the left operand. So shifting a 32bit value by 32 or more is undefined or at least not specified in the standard and each compiler may do whatever it thinks to be best.
Heinz
First, please find the setting in your news posting software where you
tell it to insert line breaks at some interval in the range of 65 to
89 characters. Thank you.
Next, you are partially correct. The value of the right operand must
not only be less than the width in bits of the (promoted) left
operand, it must also be greater than or equal to 0.
Both a negative right operand, or one as large or larger than the
number of bits in the promoted left operand cause undefined behavior.

Jack Klein
Home: http://JKTechnology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/Cfaq/top.html
comp.lang.c++ http://www.parashift.com/c++faqlite/
alt.comp.lang.learn.cc++ http://www.contrib.andrew.cmu.edu/~a...FAQacllc.html  
P: n/a
 gs*****@DigitalGlobe.com (GGG) wrote in message news:<98**************************@posting.google. com>... Ah... I figured out what was really going on here.
I originally got no compiler warnings from my real program, as the value I was shifting by was a variable.
I should have payed better attention to my little test program.
uint32_t x = 1 << 32; //here, x is still 1. Shift any 32 bit int by 32 bits and it stays the exact same number
That gives a compiler warning because I am shifting by the size of the data type. The problem here is that it is really just multiplying by 2^32. So... it stays that same.
No, it doesn't. Unsigned arithmetic, including multiplying, works modulo
2^n. Multiplying by 2^32 modulo 2^32 always gives you 0.
What happens has been pointed out before: undefined behavior.
Regards,
Michiel Salters  
P: n/a

Jack Klein <ja*******@spamcop.net> wrote in message news:<dg********************************@4ax.com>. .. On Wed, 26 May 2004 22:42:52 +0200, "Heinz Ozwirk" <wa******@gmx.de> wrote in comp.lang.c++:
"GGG" schrieb
uint32_t x = 5; uint32_t y = x << 32; uint32_t z = x << 32;
In the above example y and z are both still 5. Why is this?
Now I understand doing a shift like this seems silly, but in this code sometimes the resulting shift validly turns out to be exactly the number of bits in that data type, and expects the result to be 0.
It doesn't matter what you are expecting. The behaviour of shifts defined only if the value of the right operand is less than the number of bits in the left operand. So shifting a 32bit value by 32 or more is undefined or at least not specified in the standard and each compiler may do whatever it thinks to be best.
Heinz
First, please find the setting in your news posting software where you tell it to insert line breaks at some interval in the range of 65 to 89 characters. Thank you.
Next, you are partially correct. The value of the right operand must not only be less than the width in bits of the (promoted) left operand, it must also be greater than or equal to 0.
Both a negative right operand, or one as large or larger than the number of bits in the promoted left operand cause undefined behavior.
Ah, thanks for all the info. Sorry for the long lines... that always annoyed
me too, I am now just stuck no real newsgroup access anymore and it really
blows. I need to use Google to do it...(not to mentioned the ~8 hour delay
when you post on google... I just have to remeber to add in a CR manually
when I post....
Anyways, thanks for setting me straight, my first clue should have been
the compiler warnings that I wasn't paying attention too. Need to pay
better attention...
grant   This discussion thread is closed Replies have been disabled for this discussion.   Question stats  viewed: 6958
 replies: 9
 date asked: Jul 22 '05
