0

The following program should print whether the sum of the elements of the array is positive or negative:

#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];
         printf("sum %d\n ", sum);
   }


         printf("%d\n",sum);
   if(sum>-1) printf("non negative\n");
   else printf("negative\n");
   return 0;
 }

The program doesn't do what it is supposed to; it prints 'negative' no matter what array values it receives.

For example, the sum of the array written in the above program is 1, and therefore I expected the following output:

sum 1
sum -1
sum 2
sum 6
sum 1
1
non negative

While the output is:

sum 1
sum -1
sum 2
sum 6
sum 1
1
negative

Why do I get this output?

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Tree
  • 145
  • 1
  • 13

5 Answers5

1

In the expression sum > -1, the usual arithmetic conversions ("balancing") applies. Since one operand is unsigned int and the other is int, the operand -1 which is int gets implicitly converted to unsigned int. The comparison operation is carried out on type unsigned int.

In addition, unsigned variables can never hold a negative value in the first place, so the expression didn't make any sense even without the implicit conversion.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thank you. Can you please explain this in a little more detail? What does it actually mean that the operand -1 gets converted to unsigned int? What happens when a negative value is assigned to sum? I'm a bit confused, because when I wrote this: int main() { unsigned int x; x = -1; printf("%d\n",sum); return 0 } The output was -1. I read about this, and as I understand it this is because of the printf. – Tree Feb 21 '17 at 09:07
  • @Tree Simply put, C will grab the binary representation of `-1` and translate it to the unsigned equivalent. In case of 32 bit integers 2-complement, you end up with `0xFFFFFFFF`. And `sum` can never be larger than `0xFFFFFFFF`. – Lundin Feb 21 '17 at 09:15
  • @Lunding Thank you. So the statement if(sum>-1) is really if(sum>0)? I still don't get it: If -1 gets converted to unsigned int, and sum is of type unsigned int too, how come the output is 'negative' all the time? Should not it be 'non negative'? Although sum gets implicitly converted to unsigned int, I still don't know its' value, so what is actually the comparison that is being made when I execute this program? – Tree Feb 21 '17 at 09:21
  • @ Lundin * I meant -1 gets converted to unsigned int. – Tree Feb 21 '17 at 09:27
  • @Tree No, `if(sum>-1)` is the same as `if(sum > 0xFFFFFFFF)`. – Lundin Feb 21 '17 at 14:14
  • Thank you! I understand why it would print negative all the time, but why would not the value of -1 be replaced with UMAX+1? – Tree Feb 21 '17 at 14:18
  • 1
    @Tree What is "UMAX+1"? Do you mean `UINT_MAX`? Signed to unsigned conversion is carried out according to this rule: "if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type". So for this case, the compiler would internally do `-1 + UINT_MAX+1 = UINT_MAX`, which is in range of `unsigned int`. And also `UINT_MAX` happens to be `0xFFFFFFFF` on a 32 bit two's complement system. – Lundin Feb 21 '17 at 14:24
  • Thank you very much for the patience! You really helped me understand this. Yes, I meant UINT_MAX. Just one thing though, what do they mean by 'new type'? @ Lundin – Tree Feb 21 '17 at 14:32
  • @Tree This was quoted from the C standard and by "new type" they mean the unsigned type you end up with after conversion. This rule is the same for any signed to unsigned conversion, not just implicit ones. So for example if you type `(unsigned char)-1`, you'd end up with the value 0xFF (255). – Lundin Feb 21 '17 at 14:37
  • @Tree Here is a similar question with a link to "the usual arithmetic conversion" rules. http://stackoverflow.com/questions/17312545/type-conversion-unsigned-to-signed-int-char – Lundin Feb 21 '17 at 14:38
  • Thanks. I still don't get it. If I do (unsigned char)-1, then why would not it be -1+UINT_MAX+1 = UINT_MAX like before? – Tree Feb 21 '17 at 14:46
  • 1
    @Tree Because for `unsigned char` "the maximum value that can be represented in the new type" is UCHAR_MAX, 255. That is, the maximum is determined from the new type that we are converting to. – Lundin Feb 21 '17 at 14:50
  • I understand. Thank you very much for being so patient and explaining this clearly. I appreciate it :) @Lundin – Tree Feb 21 '17 at 15:00
1

Implicit Typecasting: When you define a variable as Unsigned and compare it with a negative number then that negative number is implicitly typecast. As we know negative numbers are stored in two's compliment, so -1 actually becomes a very big positive number. Now whatever the big number you supply it will always be less than that big number, that's why you are getting negative as answer all the time.

Possible solution: use ternary operator to handle + and - numbers. Thanks

Vishwajeet Vishu
  • 492
  • 3
  • 16
0

With a reasonable set of warnings enabled, a good compiler will highlight the problem:

gcc -std=c11 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds      42362568.c    -o 42362568
42362568.c: In function ‘main’:
42362568.c:19:10: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    if(sum>-1) printf("non negative\n");
          ^

It's always good advice to enable as many warnings as you can; for historical reasons, most compilers give very few warnings unless you remember to ask for them.

Note that if you change the comparison to if (sum >= 0), then you'll get a different (and perhaps more useful) message, because the literal 0 can be treated as 0u:

42362568.c:19:10: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]
    if(sum>=0) printf("non negative\n");
          ^~
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
0

When we trying to compare two different (same data type) sign's of variables ,The compiler implicitly(internally ) will treat both variables as higher signed type(unsigned type).

Hear if(sum > -1) is your code.You are trying to compare unsigned sum , signed constant so compiler internally convert -1 as unsigned . If we consider integer size as 2 bytes then sum = 1(as your code) but the -1 will be converted to unsigned value 65535 (do 2's compliment for -1) now your code will be simplified to if(sum > 65535), so the condition isFALSE that's why only always you are getting un- expected result.If you want to avoid this problem, always compare same signed type variables(if both variables are same data type , other wise there is no problem with different signed types also).

Rama rju
  • 1
  • 1
-1

two's compliment of 1 ( assume int size is 2 Bytes )

0000 0000 0000 0001 (1 binary value)

1111 1111 1111 1110 (one's compliment)

1111 1111 1111 1111 (two's compliment)(this value is 65535)

this value is replacing with -1 in your code.

Rama rju
  • 1
  • 1
  • Thank you! I'm a bit confused,I was reading about the subject, and I thought -1 would get the value of UMAX+1, why isn't it so? – Tree Feb 21 '17 at 12:27
  • Once read about two's compliment.Then you will get answer for your question. – Rama rju Feb 22 '17 at 12:52