home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c
- Path: sparky!uunet!uunet.ca!wildcan!sq!msb
- From: msb@sq.sq.com (Mark Brader)
- Subject: Re: converting unsigned int to signed int
- Message-ID: <1992Nov21.123530.25926@sq.sq.com>
- Organization: SoftQuad Inc., Toronto, Canada
- References: <19226@ucdavis.ucdavis.edu> <1992Nov20.104109.21538@thunder.mcrcim.mcgill.edu>
- Date: Sat, 21 Nov 92 12:35:30 GMT
- Lines: 97
-
- > > 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.
-