Why Does Left Shift Operation Invoke Undefined Behaviour When the Left Side Operand Has Negative Value

Why does left shift operation invoke Undefined Behaviour when the left side operand has negative value?

The paragraph you copied is talking about unsigned types. The behavior is undefined in C++. From the last C++0x draft:

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
.

EDIT: got a look at C++98 paper. It just doesn't mention signed types at all. So it's still undefined behavior.

Right-shift negative is implementation defined, right. Why? In my opinion: It's easy to implementation-define because there is no truncation from the left issues. When you shift left you must say not only what's shifted from the right but also what happens with the rest of the bits e.g. with two's complement representation, which is another story.

Get warning for left shifting a negative number

In 5 << -4, both GCC 9.1.0 and Apple LLVM 10.0.1 with clang-1001.0.46.4, targeting x86-64, issue a warning message (“left shift count is negative” for GCC and “shift count is negative” for LLVM-clang). In -4 << 3, GCC does not issue a warning, but LLVM-clang does (“shifting a negative value is undefined”).

The C standard does not require a diagnostic in either of these cases, so whether a compiler does or not is a quality of implementation issue (or, possibly, that the compiler extends C by defining left shifts of negative values and therefore does not consider it an error).

When an operand is not a constant, as in z << x and x << 3, we may surmise the compiler fails to see the operand is negative, so it does not issue a warning. In general, these expressions may have defined behavior: If x is not negative and is within suitable bounds (is not larger than the width of z in the former case and is not so large that x << 3 overflows in the latter case), the behavior is defined (excepting the possibility that z << x may overflow). The C standard does not say that left shifts with types that may have negative values, i.e., signed types, are undefined, just that left shifts with negative values are undefined. Therefore, it would be an error for the compiler to issue a warning message whenever x were a signed type in an expression such as z << x or x << 3.

Of course, given int x = -4 and the lack of any change to x between that initialization and the expressions z << x and x << 3, a compiler could deduce that the shifts are undefined in this specific case and issue a warning. This is not required by the standard, and the failure of the compiler to do so is simply a matter of the quality of the implementation of the compiler.

Is left-shifting () a negative integer undefined behavior in C++11?

Yes, I would say it's undefined. If we translate the standardese to pseudo-code:

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;

I'd say the reason why they're explicit about the right-hand operand and not about the left-hand one is that the paragrpah you quote (the one with the right-hand operand case) applies to both left and right shifts.

For the left-hand operand, the ruling differs. Left-shifting a negative is undefined, right-shifting it is implementation-defined.

undefined behavior when left operand is negative

The rules haven't changed. It's still technically undefined.

Quoting from the C standard (Section 6.5.7, paragraph 4, of n1548):

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with
zeros. If E1 has an unsigned type, the value of the result is E1 × 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.

It clearly says if E1 is not unsigned or signed with nonnegative value, the behavior is undefined.

C++ left shift overflow for negative numbers

Assuming this is C or C++, your error is because a Left Shifting a negative value is Undefined Behavior, and left shifting a signed value such that it becomes bigger than MAX_INT is also Undefined Behavior.

If you inspect the values of a and b as you run through this sequence, you will get:

-1 1
-2 2
-4 4
...
-1073741824 1073741824

At this point a&b == 1073741824. But shifting it left by 1 is the same as multiplying by 2, which would give 2147483648, which is larger than INT_MAX.

That's Undefined Behavior. The system can choose to do anything. It appears that in your case, it did the bitshift giving 0x80000000. In a signed int, this represents INT_MIN. So the next time through the loop, you are trying to left shift a negative number, which again is Undefined Behavior. Your system chose to treat this as an exception.

In general, if you are doing bit-manipulations, you are best using unsigned types.

Is left shifting unsigned int more than its bit field width, but less than its type size undefined?

There will be references to the integer promotion of the left operand. The following is the relevant promotion:

6.3.1.1.2 [...] If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; [...]

The promoted left operand is an int.


About shifting, the spec says

6.5.7.3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

The width of the promoted left operand — the width of an int — is at least 16. 5 is much less than 16.

No undefined behaviour yet.


The spec goes on:

6.5.7.4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. 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. If E1 has a signed type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

The "type of E1" refers to the type of bar.var after promotion.

E1 has an signed type. In this case, E1 can't possibly be negative, and no value of E1 multiplied by 25 would exceed what an int can represent.

No undefined behaviour yet.


Finally, we have the assignment.

6.5.16.1.2 In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.

6.3.1.3.2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.60)

No undefined behaviour there either.

Left shifting with a negative shift count

Negative integers on right-hand side is undefined behavior in the C language.

ISO 9899:2011 6.5.7 Bit-wise shift operators:

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

Is left and right shifting negative integers defined behavior?

You're not reading that sentence correctly. The standard defines it if: the left operand has a signed type and a non-negative value and the result is representable (and previously in the same paragraph defines it for unsigned types). In all other cases (notice the use of the semicolon in that sentence), i.e, if any of these conditions isn't verified, the behaviour is undefined.



Related Topics



Leave a reply



Submit