This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: portable signed right shift


> That's true, you need to actually write something like
> 
> unsigned t;
> int i;
> 
> i = (int)((unsigned)-1 >> 1 & t) - (int)(~((unsigned)-1 >> 1) & t);

That doesn't avoid the undefined behaviour, if t is greater than INT_MAX,
you get two overflows:
first converting (INT_MAX+1U) to an int (INT_MIN), and then subtracting
that from a positive int, i.e. arithmetically you get the original value
of t, but of course that overflows.

On two-s complement machines you can do:

i = (int)((unsigned)-1 >> 1 & t) + INT_MIN * -(int)(t / (INT_MAX + 1U))

but of course you get a different INT_MIN on a one's complement machine,
and this can't be fixed by changing the multiplication to use three
factors, either, because the desired result is out of range if not zero.

So it's more like:

i = ((int)((unsigned)-1 >> 1 & t)
     - (int)((~((unsigned)-1 >> 1) & t) >> 1)
     - (int)((~((unsigned)-1 >> 1) & t) >> 1));


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]