Is left-shifting a negative int
Undefined Behavior in C++11?
The relevant Standard passages here are from 5.8:
2/The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated
bits are zero-filled. If E1 has an unsigned type, the value of the
result is E1 × 2E2, reduced modulo one more than the maximum value
representable in the result type. Otherwise, if E1 has a signed type
and non-negative value, and E1×2E2 is representable in the result
type, then that is the resulting value; otherwise, the behavior is
undefined.
The part that confuses me is:
Otherwise, if E1 has a signed type and non-negative value, and E1×2E2
is representable in the result type, then that is the resulting value;
otherwise, the behavior is undefined.
Should this be interpreted to mean that left-shifting any negative number is UB? Or does it only mean if you LS a negative and the result doesn't fit in the result type, then it's UB?
Moreover, the preceding clause says:
1/The shift operators << and >> group left-to-right.
shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
The operands shall be of integral or unscoped enumeration type and
integral promotions are performed.
The type of the result is that of the promoted left operand. 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.
This makes it explicit that using a negative number for one of the operands is UB. If it were UB to use a negative for the other operand, I would expect that to be made clear here as well.
So, bottom line, is:
-1 << 1
Undefined Behavior?
@Angew provided a psudocode interpretation of the Standardese which succinctly expresses one possible (likely) valid interpretation. Others have questioned whether this question is really about the applicability of the language "behavior is undefined" versus our (StackOverflow's) use of the phrase "Undefined Behavior." This edit is to provide some more clarification on what I'm trying to ask.
@Angew's interpretation of the Standardese is:
if (typeof(E1) == unsigned integral)
value = E1 * 2^E2 % blah blah;
else if (typeof(E1) == signed integral && E1 >= 0 && representable(E1 * 2^E2))
value = E1 * 2^E2;
else
value = undefined;
What this question really boils down to is this -- is the correct interpretation actually:
value = E1 left-shift-by (E2)
switch (typeof(E1))
{
case unsigned integral :
value = E1 * 2^E2 % blah blah;
break;
case signed integral :
if (E1 >= 0)
{
if (representable(E1 * 2^E2))
{
value = E1 * 2^E2;
}
else
{
value = undefined;
}
}
break;
}
?
Sidenote, in looking at this in terms of psudocode makes it fairly clear in my mind that @Agnew's interpretation is the correct one.
See Question&Answers more detail:
os