From: wkaufman@us.oracle.com
Newsgroups: comp.lang.c
Date: 18 Jul 92 20:36 MDT
Subject: Re: unsigned long to long without lossa
Nf-ID: #R:brself.711346221@hal:-680706142:1992Jul18.163616.13897@oracle.us:-1978910101:001:4816
Nf-From: us.oracle.com!wkaufman    Jul 18 20:36:00 1992


In article <1992Jul17.201215.19749@wyvern.twuug.com> alpha@wyvern.twuug.com (Joe Wright) writes:
] brself@hal.gnu.ai.mit.edu (Ben Self) writes:
] : 
] : Can anyone please tell me a portable (one which does not step on either
] : the ANSI or POSIX standards) way to preserve the bit order and precision
] : of an unsigned long that has to be crammed into a variable of type long.

    If (ulong_val > INT_MAX), there's not much you can do.  Someone else
(name lost) suggested the following code:

        if (ulong_val > INT_MAX)
            slong_val = ulong_val - INT_MAX;

    First, there may be problems if you're not doing this on a two's
complement machine (OK, I don't know *what* problems--I'm just
guessing).

    Second, it assumes that negative numbers are acceptable to whatever
takes a Message type (which may well be true--some info from the
poster on the Message type and the message codes could help).

    And third, I'm not sure this will work, because (long) isn't big
enough for the left side of the minus sign, and (unsigned long) can't
take the negative value of the whole, so I don't know if the machine
could find an suitable intermediate value for the calculation.  (If I'm
wrong, someone will be along in a bit to correct me, in a violent
manner.)

] : I know that ANSI treats unsigned long as wider type than long and if
] : mixed all values are promoted to unsigned long.

    In real life (as opposed to ANSI), some machines will have the same
top value for both--signed-bit machines, for example.  But, for the
majority of machines you'll use, unsigned will be one bit longer.  (I
almost wrote, "...a bit longer", which isn't quite the same thing.
Amazing how technical terms can mangle the language.)

] : I know they both have the same size; surely there must be a way to
] : assure there is no loss of information in a portable way.

    If Message is your own invention (not buried in some vendor's
header, for example), and you can't change the numbers, you might want
to just add a bit to the type, like

        if (ulong_val > INT_MAX)
          {
            message.long_val = ulong_val - INT_MAX;
            message.big_number = 1;
          }
        else
          {
            message.long_val = ulong_val;
            message.big_number = 0;
          }

and reconstruct the ulong_val the other way.

    If, on the other hand, Message *isn't* your own invention, but the
message codes *are*, lower the numbers--assuming you're on a 32-bit
machine, you don't really have two billion messages, right?  Or, even if
you do, you could use negative numbers, right?

    If you don't own either the message codes *or* the Message type,
well,...

] Most of my posts generate flames from 'knowledgable' readers and
] alternatives to any suggestions.  So here goes..

    I *swear*, this is *not* a flame!

] Historically, 'unsigned long' has been supported by the language
] but not by the implementation.

    Actually, if the hardware supports unsigned types, it's likely that
the compiler will, too.  But, yeah, the above may be true for PCs, and
many of the RISC machines out now,...

]  This has to do with the complexity
] (in the implementation) of treating the two differently.  Really, 
] why should we treat 'unsigned long'?  Nobody needs an integer bigger
] that 2 billion, surely.  

    ...if you're lucky enough to be on a 32-plus-bit machine.  In the
original poster's case, 2 billion is probably good enough for the number
of possible messages--who'd even want to type in 2 billion messages?!?
But for calculating the US national debt, for example, it's not enough.
(Well, OK, 4 billion isn't large enough either,...)

    (As a random anecdote, a friend was working for AT&T during the time
of The Great Breakup, writing software to figure out what money went
where.  Early on, he wasn't sure whether to display values in millions
or billions,... When you get that far up there, every bit helps.)

] If the ANSI standard provides different sizes for 'long int' and 
] 'unsigned long int' it is news to me.  I would guess that all
] implementations will have them the same size in any case.

    On a two's-complement machine, half the space is taken up with
negative numbers, right?  If you drop those (i.e., if you use a real
unsigned integer type), you'll increase the top value.  On this Sun
machine, for instance, limits.h lists

        #define	INT_MAX			 0x7FFFFFFF
        #define	UINT_MAX		 0xFFFFFFFF

    This isn't a wackiness of the C implementation, it's a fact of the
two's-complement integer space.

                                           -- Bill K.

Bill Kaufman,          | "...all conscious species are plastic and
Corporate Lackey       |  all plastic species are conscious."
wkaufman@us.oracle.com |                     -- Yew-Kwang Ng