Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C, how to get calculate the negative of an unsigned quantity

In K&R ANSI C book, section A.7.4.5 (Unary Minus Operator) it is stated:

... The negative of an unsigned quantity is computed by subtracting the promoted value from the largest value of the promoted type and adding one; ...

How exactly is this calculated? Could you give a short C example?

I don't see how this could yield the negative of, say, 200u: subtracting 200 from a max value of any integral type (signed or unsigned) and adding 1 does not result in -200.

I know what the Unary minus does - the problem is that I don't see how the result is calculated according to the description.

like image 837
Ree Avatar asked Nov 09 '09 12:11

Ree


4 Answers

Unsigned values can't be negative, so -200 is not a possible result.

What it's saying is that if UINT_MAX is 65535 on your system, then the result of:

unsigned a = 200;
unsigned b = -a;
long c = -a;

will leave 65336 in both b and c.

If your system has UINT_MAX > LONG_MAX (typically because int and long are the same size), you will need to use long long for c (although note that there's not even any guarantees that that's long enough).

This detail (that the result of negating an unsigned number is another, necessarily positive, unsigned number) can result in some unexpected effects if you do not understand it. For example, in this code the first example prints "true" but the second example prints "false":

int a = 200;
unsigned b = 200;
if (-a < 100) printf("true\n"); else printf("false\n");
if (-b < 100) printf("true\n"); else printf("false\n");

(note that we are not storing the result of the negation operator anywhere - that is not the issue).

like image 129
caf Avatar answered Nov 15 '22 05:11

caf


Apparently you missed the word unsigned in the description you quoted. This is the key word in this case. In C language the "negative" of an unsigned quantity is still unsigned, meaning that it is not really negative. Unsigned values can't ever be negative, by definition. They are always positive or 0. Arithmetic of unsigned values in C is modulo arithmetic or, in simple words, unsigned quantities "wrap around" when you perform arithmetical operations on them. Unary negation is not an exception. Calculating -n when n is unsigned is no different from calculating 0 - n. If n is unsigned int and its value is 200 the expected result is not -200, but rather UINT_MAX - 200 + 1, which is exactly what the quote is telling you.

like image 43
AnT Avatar answered Nov 15 '22 05:11

AnT


It describes operations to implement modular arithmetic, i.e. it computes a value such that

a + (-a) == 0

This makes the negated unsigned number behave closely to a negated signed number.

On machines where the number representation is two's complement (such as x86), this is done by just treating the bit pattern of the unsigned number as an ordinary signed number, and using the machine's standard "negate" instruction.

like image 6
unwind Avatar answered Nov 15 '22 05:11

unwind


Another question has touched this topic already

Example

unsigned char i = -10;
printf("%u\n",i);

Result

246
like image 4
Peter Lindqvist Avatar answered Nov 15 '22 05:11

Peter Lindqvist