问题
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?
回答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.
回答2:
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
回答3:
the output because of your declaration of sum
variable, you declared it as a unsigned sum
just change the unsigned sum
to signed sum
or int sum
回答4:
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");
^~
回答5:
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).
回答6:
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.
来源:https://stackoverflow.com/questions/42362568/why-does-my-test-of-sign-always-report-negative