Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Maximum value for typedef'd type

5 views
Skip to first unread message

Fred L. Kleinschmidt

unread,
Sep 11, 2003, 12:39:46 PM9/11/03
to
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.
It may be any of the following:
#typedef Newtype short;
#typedef Newtype unsigned short;
#typedef Newtype int;
#typedef Newtype unsigned int;
#typedef Newtype long;
...etc.

The actual typedef used depends on the platform; this definition is made
in a third-party header over which I have no control.

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 */
/*
* 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 );
}

--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Common User Interface Services
M/S 2R-94 (206)544-5225

Bertrand Mollinier Toublet

unread,
Sep 11, 2003, 1:09:55 PM9/11/03
to
Fred L. Kleinschmidt 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.
> It may be any of the following:
> #typedef Newtype short;
> #typedef Newtype unsigned short;
> #typedef Newtype int;
> #typedef Newtype unsigned int;
> #typedef Newtype long;
> ...etc.
>
> The actual typedef used depends on the platform; this definition is made
> in a third-party header over which I have no control.
>
> 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 */
> /*
> * 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 );
> }
>
Yes, there are gotchas including, if I am not mistaken, undefined
behaviour in some cases, as evidenced by the thread entitled "Many happy
returns" that has been running this week.

--
Bertrand Mollinier Toublet
int main(){char*strchr();int j=1234;char t[]=":@abcdefghij-lmnopqrstuv"
"wxyz.\n",*i="iqgbgxmbbla.llsvoaz:zdxylaxejivnidhd@ttopnjeftuh-i";while
(*i){j+=strchr(t,*i++)-t;j%=sizeof t-1;putchar(t[j]);}return 0;}

Joona I Palaste

unread,
Sep 12, 2003, 3:33:36 AM9/12/03
to
Fred L. Kleinschmidt <fred.l.kl...@boeing.com> scribbled the following:

> 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.
> It may be any of the following:
> #typedef Newtype short;
> #typedef Newtype unsigned short;
> #typedef Newtype int;
> #typedef Newtype unsigned int;
> #typedef Newtype long;
> ...etc.

This is the entirely wrong syntax for typedef. # marks a preprocessor
directive, while typedef is a feature of the actual C language.
Presumably you mean:
typedef short Newtype;
typedef unsigned short Newtype;
and so on.

--
/-- Joona Palaste (pal...@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"The obvious mathematical breakthrough would be development of an easy way to
factor large prime numbers."
- Bill Gates

Kevin Bracey

unread,
Sep 12, 2003, 8:35:50 AM9/12/03
to
In message <3F60A552...@boeing.com>

"Fred L. Kleinschmidt" <fred.l.kl...@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/

Dan Pop

unread,
Sep 12, 2003, 10:07:36 AM9/12/03
to
In <3F60A552...@boeing.com> "Fred L. Kleinschmidt" <fred.l.kl...@boeing.com> writes:

>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.
>It may be any of the following:
>#typedef Newtype short;
>#typedef Newtype unsigned short;
>#typedef Newtype int;
>#typedef Newtype unsigned int;
>#typedef Newtype long;
>...etc.

You may want to learn C before worrying about such issues. typedef is
not a preprocessor directive and it has a completely different syntax than
the #define directive.

>The actual typedef used depends on the platform; this definition is made
>in a third-party header over which I have no control.
>
>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)

This is definitely not a valid function definition.

>{
> static Newtype x = ~0; /* Fill with 1's */
> /*
> * 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 );
>}

This is all wrong. If Newtype is signed, the most likely result is 1.

The trick is to use the widest unsigned type (unsigned long in C89) for
this purpose:

unsigned long max = -1;
while ((Newtype)max < 0 || (Newtype)max != max) max >>= 1;
return max;

The code exploits the fact that the maximum value is one less than a
power of two. It is theoretically unsafe on C99 implementations, where
(Newtype)max is allowed to raise an implementation-defined signal if
the value of max cannot be represented by Newtype.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan...@ifh.de

Fred L. Kleinschmidt

unread,
Sep 12, 2003, 10:38:16 AM9/12/03
to

Joona I Palaste wrote:
>
> Fred L. Kleinschmidt <fred.l.kl...@boeing.com> scribbled the following:
> > 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.
> > It may be any of the following:
> > #typedef Newtype short;
> > #typedef Newtype unsigned short;
> > #typedef Newtype int;
> > #typedef Newtype unsigned int;
> > #typedef Newtype long;
> > ...etc.
>
> This is the entirely wrong syntax for typedef. # marks a preprocessor
> directive, while typedef is a feature of the actual C language.
> Presumably you mean:
> typedef short Newtype;
> typedef unsigned short Newtype;
> and so on.
>

Yeah, I did a cut/paste from a print that uses "#" as a linestart
indicator, and forgot to remove it to show the real source text.


> --
> /-- Joona Palaste (pal...@cc.helsinki.fi) ---------------------------\
> | Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
> | http://www.helsinki.fi/~palaste W++ B OP+ |
> \----------------------------------------- Finland rules! ------------/
> "The obvious mathematical breakthrough would be development of an easy way to
> factor large prime numbers."
> - Bill Gates

--

Fred L. Kleinschmidt

unread,
Sep 12, 2003, 11:22:06 AM9/12/03
to Kevin Bracey

I know that NewType must be one of the six
(unsigned/signed)(short/int/long).
Thus here is what I am now trying:

Newtype GetMaximum Newtype(void)
{
static Newtype x = -1; /* negative if signed, MAXVAL if unsigned */
static int len = sizeof(Newtype);

if ( x > 0 ) {
return x; /* Newtype is an unsigned type */
}
/* Newtype is a signed type */
if (len == sizeof(short)) {
return (Newtype)USHRT_MAX;
}
else if (len == sizeof(long)) {
return (Newtype)ULONG_MAX;
}
return (Newtype)INT_MAX; /* as a default, if not short or long */

Jirka Klaue

unread,
Sep 12, 2003, 11:41:22 AM9/12/03
to
Fred L. Kleinschmidt wrote:
...

> I know that NewType must be one of the six
> (unsigned/signed)(short/int/long).
> Thus here is what I am now trying:
>
> Newtype GetMaximum Newtype(void)
> {
> static Newtype x = -1; /* negative if signed, MAXVAL if unsigned */
> static int len = sizeof(Newtype);
>
> if ( x > 0 ) {
> return x; /* Newtype is an unsigned type */
> }
> /* Newtype is a signed type */

OK, so far.

> if (len == sizeof(short)) {
> return (Newtype)USHRT_MAX;

USHRT_MAX? For a signed variable?

Furthermore, the size of a type is not related to the range representable
by this type. Have a look at Dan Pop's reply for a possible solution.

Jirka

Joona I Palaste

unread,
Sep 12, 2003, 12:38:23 PM9/12/03
to
Fred L. Kleinschmidt <fred.l.kl...@boeing.com> scribbled the following:
> Joona I Palaste wrote:
>> Fred L. Kleinschmidt <fred.l.kl...@boeing.com> scribbled the following:
>> > 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.
>> > It may be any of the following:
>> > #typedef Newtype short;
>> > #typedef Newtype unsigned short;
>> > #typedef Newtype int;
>> > #typedef Newtype unsigned int;
>> > #typedef Newtype long;
>> > ...etc.
>>
>> This is the entirely wrong syntax for typedef. # marks a preprocessor
>> directive, while typedef is a feature of the actual C language.
>> Presumably you mean:
>> typedef short Newtype;
>> typedef unsigned short Newtype;
>> and so on.
>>

> Yeah, I did a cut/paste from a print that uses "#" as a linestart
> indicator, and forgot to remove it to show the real source text.

Looks like the print uses really strange syntax then, because the
syntax of "typedef" is that the new type (Newtype in this case) must
appear *after* the actual type, not before it.
In other words: the print reads:
typedef Newtype short;
when it should read:
typedef short Newtype;

0 new messages