简体   繁体   中英

What happens if we assign a negative int into an unsigned int

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;
}

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 (eg -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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM