In message <3F***************@boeing.com>
"Fred L. Kleinschmidt" <fr*****************@boeing.com> wrote:
I need to know the largets value representable in a variable. However, I
do not know the variable's true type - only that it is some kind of int.
Here is my code that appears to work on the platforms I am using. Have I
missed anything here? Any gotchas?
Newtype GetMaximum Newtype(void)
{
static Newtype x = ~0; /* Fill with 1's */
To reliably fill it with 1's, that has to be "~(Newtype) 0".
/*
* If x<0, then Newtype was a signed entity, so we need to negate
it.
* Note the compiler may complain if Newtype is unsigned.
*/
return ( (x < 0) ? -x : x );
}
That assumes sign-and-magnitude representation for signed integers, as far as
I can see. That's not common, but it may match your platform. For 2's
complement you end up returning 1, and for 1's complement you either return 0
or invoke undefined behaviour.
A better start would be
static Newtype x = -1;
That will set x to -1 if it is signed, and to NEWTYPE_MAX if it is unsigned,
on any system. Thus we can next say
if (x > 0) return x;
Signed types are much harder to probe without invoking undefined behaviour or
relying on outside knowledge. Let's try though. C guarantees one of 3
representations for signed integers - sign-and-magnitude, 2's complement or
1's complement.
I think you can safely determine which representation is in use safely by
saying
x = ~(Newtype) 1;
x now has all its value bits set except the "1" bit, and the sign bit is set.
What exactly that means depends on the representation.
if (x == -1)
/* representation is 1's complement */;
else if (x == -2)
/* representation is 2's complement */;
else
/* representation is sign-and-magnitude */;
Note that this test (indeed probably the whole function) can be evaluated at
compile time.
Sign-and-magnitude is straightforward. For that one we just
return (-x) + 1;
For the other two, we've got a problem. We need to set all the value bits,
and clear the sign bit, but how to achieve this without invoking undefined
behaviour? Integer overflow is undefined, left-shift of positive values
outside the range is undefined, and whether you can have the sign bit set and
all value bits clear is implementation-defined.
I can't see any way of doing it without making some sort of assumption. The
safest may be to assume that left shift overflow throws away the excess bits
or moves them through the sign bit, and do something like:
x = 0xFF; // avoids trap representations at end of shift
while ((x << 1) > x)
x <<= 1;
return x | (x >> 8);
If there is a nice, portable answer to this, I can't see it :(
--
Kevin Bracey, Principal Software Engineer
Tematic Ltd Tel: +44 (0) 1223 503464
182-190 Newmarket Road Fax: +44 (0) 1223 503458
Cambridge, CB5 8HE, United Kingdom WWW:
http://www.tematic.com/