tech-toolchain archive

# Re: minus operator applied to unsigned type

On Mon, 29 Nov 2010, der Mouse wrote:
> > My compiler is confused. What does this mean?
> >     d_val = str[0] == '-' ? -(double)-l_val : (double)l_val;
>
> I'm not sure why the -(double)-l_val construct.  I suspect the intent
> is to convert an unsigned long holding a signed long's bit pattern to a
> double with the same value as the signed long.

Yes, that's what I assumed, and I believe that the original code
correctly implements that intent.  I would probably have prenthesised it
like this:

d_val = (str[0] == '-' ? -(double)(-l_val) : (double)l_val);

> If so, I can't see why not (double)(long)l_val;

That invokes undefined behaviour, if l_val is an unsigned long whose
value is outside the range of positive integers that that can be
represented by a signed long.  That will happen whenever the intent is
to deal with a negative number, because negative numbers stuffed into
unsigned long variables look like large positive numbers.

In this code:

signed long svar;
unsigned long uvar;
svar = -1;   /* A */
uvar = svar; /* B */
svar = uvar; /* C */

assignment B stores a large positive value into uvar, and assignment C
invokes undefined behaviour because that large positive value is too
large to be represented as a positive value in svar.

> indeed, I think -(double)-l_val equals
> (double)(long)l_val except when l_val holds the (bit pattern of the)
> most negative long - or if signed longs don't use two's complement, I
> suppose, which it seems to me it is unlikely the code is designed to
> accommodate.

I think I agree with you about what likely to happen on a machine that
uses two's complement, but I believe that the original code would have
worked with any underlying representation, and even when l_val is
intended to represent the most negative signed long.

> > There are several of these (for my compiler ambiguous) constructs in
> > bmake. [...] I solved them just by adding a zero - hope that's what
> > was originally meant.

As Mouse said, there's nothing ambiguous about the original code, but
changing -(double)-l_val to -(double)(0-l_val) will retain the same
meaning.  You could also try -(double)(-l_val).

--apb (Alan Barrett)

Home | Main Index | Thread Index | Old Index