Re: Left shift of negative value

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 01/12/15 18:26, Richard Earnshaw wrote:
On 01/12/15 17:10, Andrew Haley wrote:
On 12/01/2015 05:08 PM, Andrew Haley wrote:
On 12/01/2015 05:01 PM, Richard Earnshaw wrote:
On 01/12/15 16:07, Andrew Haley wrote:
Do we support left shift of a negative value?  Technically it's
undefined and ubsan warns about it.  However, a ton of software would
surely break if we didn't do the obvious right thing.  I can't find
anything in the GCC manual.

I don't believe we do, or can as of today.  Firstly, there are two
possible 'obvious' behaviours: 1) The value is treated as signed and a
negative shift turns into a positive shift in the other direction; 2)
The value is treated as unsigned and the value is treated by a massive
shift in the same direction that exceeds the normally supported range of
the type.  Which one is the default will probably depend on your hardware.

Consider the case where the value is in a variable.  To support negative
shifts as reversed shifts on machines where they don't automatically
convert negative values to reversed shifts you'd have to do an explicit
range check before every shift using that value.  Something I know we
don't do today since I've never seen such checks come out on ARM, nor
are there any hooks in the compiler to deal with it.

No, a shift *of* a negative value, not a shift *by* a negative value!
i.e. an arithmetic right shift.

That explanation was even more confusing.  Sorry.

I mean something like  -12345 << 4

Andrew.



Yeah, sorry, I mis-parsed your original email.

I'd expect that to work on practically all 2's complement machines.  And
I'd also expect right shifts to work correctly with GCC by doing
sign-bit replication on a 2's complement machine.


I would not "expect it to work", because I don't understand what you would expect the result to be. Bit shifts make sense for unsigned values. If you mean "-12345 * 16", then write that.

If a compiler does not know that the value you are shifting happens to be negative, then the result you get is probably equivalent to the multiply, for most common cpus. But if the compiler knows for sure that the value is negative, then it knows that the operation is undefined - and therefore that the programmer does not care about the result, or what happens when program flow reaches that point. The compiler can do anything it likes at this point, including omitting any instruction for the shift or launching nasal daemons.

Now, it happens that gcc currently defines the behaviour of such shifts - this is an extension to gcc. For any given gcc version, if this behaviour is documented, then you can rely on it. But it is conceivable that gcc's behaviour here could change in the future, and it can certainly vary between different compilers. So use shifts on negative values with caution.

<https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html>






[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux