assigning an integer to the negation of a cast of a short to a u_short
Guy Harris
guy at auspex.UUCP
Wed Dec 21 04:18:48 AEST 1988
>If I run this program on a VAX 11/780 using 4.3 BSD, I obtain -1 as the
>answer. However, if I run this on a SUN using SUN OS 3.5, I obtain 65535
>as the answer.
If I run this on a Sun-3 (and probably on other Suns - it's not an
acronym any more, BTW), I get -1.
>Who is right?
Well, let's see:
The expression, when fully parenthesized, is
-((unsigned short)j)
i.e., the cast is done first, and then the negation.
K&R First Edition says, under 7.2 Unary operators:
The result of the unary - operator is the negative of its
operand. The usual arithmetic conversions are performed. The
negative of an unsigned quantity is computed by subtracting its
n
value from 2 , where "n" is the number of bits in an "int".
Under 6.6 Arithmetic conversions, it says:
First, any operands of type "char" or "short" are converted to
"int", and any of type "float" are converted to "double".
(...stuff about "double" and "long", which doesn't matter here...)
Otherwise, if either operand is "unsigned", the other is
converted to "unsigned" and that is the type of the result.
Unfortunately, "unsigned short" didn't exist in K&R First Edition C, so
the question is "what do the 'usual arithmetic conversions' do to an
'unsigned short' in more modern C?" If it gets widened to "int", the
right answer is -1; if it gets widened to "unsigned int", the right
answer is 2^32 - 1 on a machine with 32-bit "int"s.
K&R Second Edition, based on some ANSI C draft, says:
A7.4.5 Unary Minus Operator
...The integral promotions are performed....
and
A6.1 Integral Promotion
A character, a short integer, or an integer bit-field, all
either unsigned or not, may be used in an expression wherever an
integer may be used. If an "int" can represent all the values
of the original type, then the value is converted to "int";
otherwise the value is converted to "unsigned int".
Since, if "int" has more bits than "unsigned short", any "unsigned
short" value can fit into an "int" (that is the case on both the VAX and
on all Suns), the "unsigned short" value of "(unsigned short)j" is
converted to "int" before it is negated; thus, the right answer in dpANS
C is -1.
In "modern but not dpANS" C, though, I'm not sure. At least one draft
of the ANSI C Rationale I saw spoke of a change from
"unsignedness-preserving" to "value-preserving" conversion rules, the
latter being pretty much the rules described under "Integral Promotion".
As such, the old rules may have been "unsignedness-preserving"; I
presume this means that the "usual arithmetic conversions" cause the
"unsigned short" to be promoted to "unsigned int". What this means is
that an "unsigned short" value of "1" is promoted to an "unsigned int"
value of "1"; this is negated, yielding 2^32-1. This is then assigned
to an "int", yielding -1....
So it appears 65535 isn't right in dpANS C nor, probably, in "modern but
not dpANS" C.
More information about the Comp.lang.c
mailing list