Marc wrote:
Hi,
I've been lurking on clc for a few months now, and want to start by
thanking the regulars here for opening my eyes to a whole new dimension
of "knowing c". Considering I had never even touched the standards a
year ago, though I graduated in embedded SW development...
Anyway, to the problem at hand: I've stumbled upon the following
construct at work recently, and cannot really make up my mind about the
standard's take on the matter.
int a;
unsigned int b;
if(a < 0) {
b = -a;
}
I just can't decide if this is valid when a's value is -32768 (admitting
16 bit ints). I can't see how the standard's wording on unary minus
semantics allows for 2's complement asymmetry. C99 says:
"The result of the unary - operator is the negative of its (promoted)
operand. The integer promotions are performed on the operand, and the
result has the promoted type." (I'm also slightly suspicious about the
disappearance of "value" as compared to the semantics of unary plus...)
Unless I'm mistaken, a won't be promoted (being an int), so there might
be no such thing as "the negative of its (promoted) operand"? I feel
like the standard tells me I might end up with an int worth 32768...
(still assuming 16 bit ints)? Or should I consider there is an implied
"if-it-fits-otherwise-overflow"?
I couldn't find any help through google or in the FAQ, so I'd really
appreciate any clarification.
Yes, two's complement is asymmetric about zero: there
is a negative number whose absolute value is not representable.
(The Standard actually permits an implementation to dodge this
asymmetry by defining "all ones" to be a trap representation;
I've never heard of an implementation that does so.)
However, that doesn't mean unary minus is undefined: it's
only undefined if its operand has an inappropriate value. This
is really no different from the situation with binary minus:
"The result of the binary - operator is the difference
resulting from the subtraction of the second operand
from the first." (6.5.6/6)
This is not to be taken as implying that all subtractions must
produce mathematically correct results: `INT_MIN - 42', for
example, is clearly not going to produce a value less than
INT_MIN.
When this sort of thing happens, another provision of the
Standard takes over:
"If an _exceptional condition_ occurs during the
evaluation of an expression (that is, if the result
is not mathematically defined or not in the range of
representable values for its type), the behavior is
undefined." (6.5/5)
So: If you try to negate (or take the absolute value of)
INT_MIN on a system where `INT_MIN + INT_MAX' is not zero, the
C language does not specify the outcome -- anything can happen,
at least in principle. The commonest behavior is that the
overflow is ignored, and the resulting representation (all ones)
is equal to INT_MIN again: INT_MIN is its own negation on most
two's-complement systems. However, this should be thought of
as a quirk of those systems, not as part of the C language.
--
Eric Sosman
es*****@acm-dot-org.invalid