0

Simply as title says.

I had a line like this foo | (~(-1 >> 1)); which intension it was to keep foo as it is if it is negative and setting the first bit in case it isn't set.

(by to keep it as it is, I mean the bits)

But it just didn't change anything for foo.

after dbeugging I figgured out that -1 >> 1 evaluates to -1. I'm pretty sure right shifting does fill up from the left with 0's But this seems to filled a 1 while that would explain why FF >> 1 would evaluate to FF but this seems unreasonable to me aswell.

So what am I doing wrong / where is my error in my thinking about this?

dhein
  • 6,431
  • 4
  • 42
  • 74
  • 2
    right bit shift of negative numbers is compiler implementation specific. – Jarod42 Sep 18 '15 at 08:35
  • @DavidSchwartz: But why `1111` >> 1 becomes `1111` when I elarned it shifts 1 right filling with `0`? Why the shifting is even there if it is anyway doing the same as some other operations? – dhein Sep 18 '15 at 08:35
  • 1
    _" I'm pretty sure right shifting does fill up from the left "_ It's implementation defined, as [this source](http://en.cppreference.com/w/cpp/language/operator_arithmetic) says. – πάντα ῥεῖ Sep 18 '15 at 08:35
  • "I'm pretty sure right shifting does fill up from the left with 0's" – no, it's implementation-defined. Apparently, your implementation defines it as an **arithmetic** (rather than a logical) right shift. – The Paramagnetic Croissant Sep 18 '15 at 08:35
  • https://en.wikipedia.org/wiki/Arithmetic_shift see "Non-equivalence of arithmetic right shift and division". – Marius Bancila Sep 18 '15 at 08:36
  • @Zaibis On your platform, it sign extends. It doesn't fill with zeroes. As for your last question, it's ill-formed. You're asking "why should I be able to shift by any amount if shifting by one can be done some other way". Well, people shift by values other than one. You may notice that there is no special "shift right by one" operator. – David Schwartz Sep 18 '15 at 08:37
  • @Bathsheba perhaps because it's trivial to answer using the knowledge obtainable from a beginners' tutorial about C++ arithmetic operators? – The Paramagnetic Croissant Sep 18 '15 at 08:38

3 Answers3

4

Per standard, right shift is implementation-defined (5.8.3):

The value of E1 >> E2 is E1 right-shifted E2 bit positions. <...> If E1 has a signed type and a negative value, the resulting value is implementation-defined.

For example, this MSDN article mentions that for Microsoft’s compiler

The right-shift operator causes the bit pattern in shift-expression to be shifted to the right by the number of positions specified by additive-expression. For unsigned numbers, the bit positions that have been vacated by the shift operation are zero-filled. For signed numbers, the sign bit is used to fill the vacated bit positions. In other words, if the number is positive, 0 is used, and if the number is negative, 1 is used.

which seems to match your case.

SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
  • dont get me wrong, but I don't give anything on what microsoft says about c/c++ as they don't even have an compiler for c or c++. their MSVC is everthing but not respecting the standards of this languages. but the first thing is true. and well cited. – dhein Sep 18 '15 at 08:40
  • 1
    @Zaibis, you didn't mention which compiler you are using, so I included the first matching example I found, which happened to be Microsoft's. – SingerOfTheFall Sep 18 '15 at 08:42
  • Yeah but in my opinion a OP tagged as c++ shouldnt be getting in contact with MSVC since MSVC just isn't c++. Thats all I wanted to add from my POV – dhein Sep 18 '15 at 08:45
1

The C++ standard, [expr.shift] (Section 5.8.3) specifies for E1 >> E2: "If E1 has a signed type and a negative value, the resulting value is implementation-defined." In particular, the implementation could compile this to use use a sign-preserving shift operation.

creichen
  • 1,728
  • 9
  • 16
1

Your compiler used an arithmetic right shift instruction, rather than a logical right shift, as the standard allows. To get the behavior you want, cast to the unsigned type the same width, then shift.

Davislor
  • 14,674
  • 2
  • 34
  • 49