5

Note: This question is all about the signedness of the second operand of bit shift operators << and >>. Not at all about the first operand.

CERT INT34-C, in part: Do not shift a negative number of bits ...

Not that it needed justification, but they justify saying that it's undefined behavior.

I would have thought the rule made sense simply because if you want to shift the other way, shift by a positive number of bits using the appropriate shift operator for the other direction.

So if, in C, it is both unnecessary and undefined to shift by a negative number of bits, why is the second operand of << or >> even allowed to be signed?

MISRA-C:2004, for example (whatever you may think of MISRA like or dislike) in its section 6.10.2, as a side effect of explaining that the type of the result depends only on the first operand, says that "the second operand may be of any signed or unsigned integer type". [emphasis mine]

Why invite people to use signed second operand in bit shifting? Why allow it? Do any compilers warn against it?

talkaboutquality
  • 1,312
  • 2
  • 16
  • 34
  • It's allowed to be a formally signed type. It's not allowed to be negative. It's also not allowed to be larger than the number of the bits in the type. Does that mean C should require using a 5-bit-wide bitfield types as the right-hand operand to shifts on a 32-bit integer? Of course that would be nonsense. If you don't want a language that "invites" you to do stupid things, you should probably start looking for a different language. But other languages "invite" you to do different stupid things (like string concatenation); you'll have a hard time finding a "perfect" one... – R.. GitHub STOP HELPING ICE Apr 14 '11 at 15:15
  • @R true that I can't look for a perfect language, but there is a difference between the two requirements on the 2nd operand of bit shift: the nonnegative requirement can be enforced via the declared (and not casted) type of the operand, while the not-too-large requirement requires actually examining the value of the operand. – talkaboutquality Apr 16 '11 at 19:20

1 Answers1

4

I can't really say why things are as they are ... but I am glad I can shift by signed values:

3 in the expression a <<= 3; is an int.
If shifting by an int were illegal, you'd have to do a <<= 3U;.

Making it illegal to shift by signed values would break a lot (I do mean A LOT) of code!

pmg
  • 106,608
  • 13
  • 126
  • 198
  • Cost: perhaps less readability in complex shift expressions (but those should be avoided, for readability) Benefit: guarantees that shift count cannot be negative (prevents coding something whose behavior is undefined) So why would it be bad if signed shift count were forbidden? – talkaboutquality Apr 14 '11 at 13:57
  • @talkaboutquality: Now, consider `int a; ... b << a;`. If `a` is negative, it's a problem. Changing it to `(unsigned)a` won't help anything, because `(unsigned)a` will be a very large number, and a left shift by `(unsigned)a` will result in undefined behavior anyway. – David Thornley Apr 14 '11 at 14:15
  • @david-thornley of course I didn't mean to allow casting to unsigned, but just originally declaring second operand as unsigned. Not sure if compilers could warn and require just that. Maybe a better reference would be https://www.securecoding.cert.org/confluence/display/seccode/INT13-C.+Use+bitwise+operators+only+on+unsigned+operands particularly with, @pmg, its exception "INT13-EX2: If the right hand side operand to a shift operator is known at compile time, it is acceptable for the value to be represented with a signed type provided it is positive." – talkaboutquality Apr 16 '11 at 19:17