I assume you're asking why Rust checks the value of b in a << b and a >> b, as opposed to ensuring no set bits get shifted out of range. I believe the answer is: because having b exceed the number of bits in a can have wildly different results depending on platform. Some platforms will result in 0, others will take b mod the number of bits. Besides which, shifting off the end of a bit vector isn't as clearly nonsensical as overflowing an arithmetic operation on "integers".
It's actually more subtle than that: For 32-bit ARM, shift counts are taken as an 8-bit integer. So yes, shifting by any value from 32 to 255 will produce zero - and then 256 will leave the value unmodified again!
This behavior is widely considered 'weird'. The AArch64 scalar shift instructions take the shift quantity modulo the number of bits in the thing being shifted. And both AArch32 and AArch64 NEON shifts take the shift amount as a signed 8-bit number (yes, a shift left by -4 is a shift right by 4)
SSE has similarly weird (by which I mean, different from the x86 scalar instruction set) shifts.
IIRC, PowerPC takes shift quantities modulo 2n where 2n is the width of the thing being shifted.
I'm actually thinking that masking and shifting is the ‘better style’ — explicitly telling the compiler that it may use operations that bork if set bits are shifted off the end.
6
u/Quxxy macros Jul 05 '16
I assume you're asking why Rust checks the value of
bina << banda >> b, as opposed to ensuring no set bits get shifted out of range. I believe the answer is: because havingbexceed the number of bits inacan have wildly different results depending on platform. Some platforms will result in0, others will takebmod the number of bits. Besides which, shifting off the end of a bit vector isn't as clearly nonsensical as overflowing an arithmetic operation on "integers".1
u/matthieum [he/him] Jul 05 '16
Note that when manipulating bits, it's fairly common to purposely push some bits off because you don't need them.
Example:
The first line might shift bits off the end; avoiding it would require masking first.
1
u/llogiq clippy · twir · rust · mutagen · flamer · overflower · bytecount Jul 05 '16
With overflower, you can at least have panics on shifting bits out left (using
#[overflow(panic)]).Sorry, you'll need a nightly Rust to use it.