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