Is Left and Right Shifting Negative Integers Defined Behavior

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.

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.

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.

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 right shifting undefined behavior for negative number in cpp and in java?

Yes. It is implementation-defined.

According to C++03 5.8/3 which defines right-shifting:

The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has
an unsigned type or if E1 has a signed type and a nonnegative value,
the value of the result is the integral part of the quotient of E1
divided by the quantity 2 raised to the power E2. If E1 has a signed
type and a negative value, the resulting value is
implementation-defined.

For more information, see this link.

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.

Does it make sense for left-shifting negative integers by zero to be Undefined Behavior?

In general, you should first ask a question: what is exactly is UB and why?

It is less trivial than it sounds.

For example. Let x be min integer. Then reducing it further is considered UB even though we know what the answer should be. E.g., reducing it by 1 changes it to max integer.

But why? Because compiler/optimizer assumes that reducing an integer makes it smaller and it can optimize the code based on this assumption. Which might cause various bizarre errors in the code if an int is reduced below min integer.

So why left shifting a negative integer is a UB? Even if the left shift is 0?

Imagine you have a code y = x << c where c is unsigned. The compiler can assume here that x is not negative as otherwise it would be a UB. So if there is some compliacted logical dependance that is optimized based on the assumption that x is non-negative and you pass negative x with c = 0 it will cause the code to behave unexpectedly in random places despite the fact that the computation y = x << c makes perfect sense and will compute properly.

(Disclaimer, I haven't checked out anything specific regarding UB for << operator, just gave a general answer regarding UB in C++)

You can checkout more information regarding UB on the internet. There are a couple of videos on it in CppCon on YouTube.

Edit: on bizarre behaviors that are created due to UB. Following program

if(x > x + 1)
{
std::cout << " x is bigger than x+1 " << x << " " << x+1;
}
else
{
std::cout << " x is smaller than x+1 " << x << " " << x+1;
}

with x = 2147483647 (the max integer) will print

x is bigger than x+1 2147483647 -2147483648

if no optimization is applied (debug mode), but with -O2 enabled (release mode), it will most likely print

x is smaller than x+1 2147483647 -2147483648

negative integer number 31 = -1 not 1?

Per C99 6.5.7 Bitwise shift operators:

If E1 has a signed type and a negative value, the resulting value is implementation-defined.

where E1 is the left-hand side of the shift expression. So it depends on your compiler what you'll get.



Related Topics



Leave a reply



Submit