1

This is the code: the goal is to tell if the sum of all the array's members is positive or negative. I know that the unsigned int is a mistake because I wanted to see what it will print. So the question is why it prints negative, I mean, what an assignment of negative int to unsigned int is doing.

#include <stdio.h> #define ARR_SIZE 5 int main() { int array[ARR_SIZE] = {1,-2,3,4,-5}; unsigned sum; int i; for ( i = 0, sum=0; i < ARR_SIZE; i++ ) sum += array[i]; if( sum > -1 ) printf ("non-negative"); else printf ("negative"); return 0; } 
3
  • Unsigned integer overflow is defined in terms of modulo 2 to the CHAR_BIT * sizeof(unsigned). Commented Jun 30, 2014 at 10:13
  • There's noting unusual in the possibility to assign a negative value to an unsigned variable. The implicit conversion that happens in such cases is perfectly well defined by C language. The value is brought into the range of the target unsigned type in accordance with the rules of modulo arithmetic. The modulo is equal to 2^N, where N is the number of value bits in the unsigned recipient. This is how it has always been in C. Commented Jun 30, 2014 at 10:15
  • Your compiler should emit a warning to the effect that you are comparing expressions of differing signedness at line if( sum > -1 ) … (-1 has type int and sum is an unsigned int). If it doesn't, find how to enable this warning before any further effort. Commented Jun 30, 2014 at 10:15

3 Answers 3

1

Since "sum" is an unsigned type that the "-1" gets converted to an unsigned type as well (see below). This results in a very large number (how large depends on the machine) being compared to.

So try this conversion on paper:

-1 to a binary number (try just using 2 bytes), then that binary number to an unsigned number. The exact number is machine dependent (on your int size), but basically you are comparing sum to a very large number, thus the results you are seeing.

Committee Draft — April 12, 2011

6.3.1.8 Usual arithmetic conversions

First, if the corresponding real type of either operand is long double, the other operand is converted, without change of type domain, to a type whose corresponding real type is long double.

Otherwise, if the corresponding real type of either operand is double, the other operand is converted, without change of type domain, to a type whose corresponding real type is double.

Otherwise, if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose corresponding real type is float. 62)

Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands: If both operands have the same type, then no further conversion is needed.

Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.

The relevant part:

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.

Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

Sign up to request clarification or add additional context in comments.

Comments

1

The difference between signed and unsigned is solely in the head of the developer. For computers, numbers are just bit patterns to which certain rules are applied when it encounters certain bit patterns in the memory where the PC (program counter) happens to point.

So if you assign -1 to a 16 bit variable, the bit pattern in memory will be 1111 1111 1111 1111 (every bit will be 1 - I'm too lazy for the 32 bit variant), no matter if the variable is signed or unsigned.

The compiler should complain about the condition sum > -1 since the comparison doesn't make sense.

As a human, you expect sum is always positive so the is condition is always true.

But the compiler converts the -1 to unsigned (see below) and then compares. -1 gives you the largest possible unsigned number that you can represent for the given number of bits -> the comparison is always false since nothing could possibly be larger.

So you always get negative as output because the model in your head is wrong.

According to C99: in a binary expression where the types are the same size, the signed value is converted to unsigned. If the signed value cannot be represented in the unsigned type (e.g. -1), then "the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new [unsigned] type until the value is in the range of the new type."

Kudos go to JeremyP

12 Comments

Actually, sum > -1 has a well-defined meaning, it is just that it isn't likely to be what the programmer meant. It is not an either-or situation.
@PascalCuoq: True but that would make it even harder to understand.
You think that saying it's one of two possibilities is simpler than saying that only one thing can happen?
Your answer is very ambiguous 'Either sum is always positive (so this is always true)'... Well, sum is always positive but this is not true. I understand that you know what you're talking about, but your explanation are somehow confusing... Particulary this sentence.
@PascalCuoq: I edited my answer to make it clearer that the mistake is a mismatch between what a human expects when it reads the code and what a computer will do.
|
0

2's complement representation of -1 is 1111 1111 1111 1111 (assuming size of unsigned is two bytes) which is equal to 65535

in your case you are comparing your result with 65535 since sum is < 65535 you are getting print as negative.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.