From: msb@sq.sq.com (Mark Brader)
Subject: Re: converting unsigned int to signed int
Organization: SoftQuad Inc., Toronto, Canada
Date: Sat, 21 Nov 92 12:35:30 GMT

> > What is a safe, portable method of converting from signed int to
> > unsigned? ... I want the most negative signed value to convert to
> > 0, and the most positive signed value to (max signed int) +
> > abs(max negative signed int).
 
I hope this isn't a homework problem... because I'm going to answer it.

What I take this to be saying is that you want to convert a value
from signed int to unsigned int while adding to it the absolute
value of the most negative signed int.  Okay.  If i is the signed
int, and INT_MIN is the most negative signed int value, then this
is simply:

	(unsigned)si - INT_MIN

This works because it will convert INT_MIN to unsigned and do the
subtraction in unsigned.  The conversion and the arithmetic are
guaranteed to follow modular arithmetic properties, which is exactly
what we want here.

On an ANSI C system, INT_MIN is predefined for you and available by

	#included <limits.h>

On a pre-ANSI version of C, it may not be available as a predefined
variable, and there is no fully portable way for you to compute or
derive it within your program.



My further remarks below are in reference to the standard, but I'm
reasonably sure that they apply to all pre-ANSI implementations too.

> This may or may not be possible.  There is no guarantee that signed and
> unsigned ints have the same "range", the same number of distinct
> possible values.

If they are different, the range of unsigned ints must be larger.
This is because both types are guaranteed to occupy the same space,
and a pure binary representation is guaranteed for nonnegative values.

> To be fully portable, you have to split it up into various cases
> based on the value of the original integer.

That's the hard way.  The easy way is to do the arithmetic in the
unsigned type, where you get right semantics.

> 	#include <limits.h>
> 	signed int si;
> 	unsigned int ui;
> 
> 	if (si <= INT_MAX+INT_MIN)
> 	 { ui = si - INT_MIN;
> 	 }

Fine; included here only for context.

> #if INT_MAX+INT_MIN < -1
> 	/* this can happen only when more than half the possible int
> 	   values are negative - not possible with a two's complement
> 	   binary representation, for example */

It can't happen at all.  Nonnegative numbers have to be in pure
binary, and only one bit is allowed for the sign, so at least
half the values have to be nonnegative.

> 	else if (si < 0)
> 	 { /* some code I don't feel like working out */
> 	 }

Just as well. :-)

> #endif
> #if UINT_MAX < INT_MAX
> 	/* I'm not sure whether this is allowed; my reference is at
> 	   work and I'm at home */

No.  See above.

> 	else if (s > UINT_MAX)
> 	 { /* more messy code */
> 	 }
> #endif

Therefore, not needed.

> 	else
> 	 { ui = (unsigned int)si - (unsigned int)INT_MIN;
> 	 }

Correct, and equivalent to my code above.  However, it does not need
to be guarded by the if/else; this line does it all.
-- 
Mark Brader, SoftQuad Inc., Toronto, utzoo!sq!msb, msb@sq.com
#define	MSB(type)	(~(((unsigned type)-1)>>1))

This article is in the public domain.
Newsgroups: comp.lang.c