This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: portable signed right shift
- To: geoffk at redhat dot com
- Subject: Re: portable signed right shift
- From: Joern Rennecke <amylaar at cambridge dot redhat dot com>
- Date: Thu, 29 Mar 2001 17:04:03 +0100 (BST)
- Cc: rth at redhat dot com, dewar at gnat dot com, gcc at gcc dot gnu dot org
> 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));