为什么我的符号测试总是报告“否定”?

时间:2017-02-21 08:50:03

标签: c integer sum comparison-operators

以下程序应打印数组元素的总和是正数还是负数:

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

该计划没有按照预期进行;无论收到什么数组值,它都会打印“负数”。

例如,上面程序中写入的数组之和为1,因此我期望得到以下输出:

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

输出为:

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

为什么我会得到这个输出?

6 个答案:

答案 0 :(得分:1)

在表达式sum > -1中,通常的算术转换(“平衡”)适用。由于一个操作数为unsigned int而另一个为int,因此-1的操作数int被隐式转换为unsigned int。比较操作在类型unsigned int上执行。

此外,无符号变量首先永远不会保持负值,因此即使没有隐式转换,表达式也没有任何意义。

答案 1 :(得分:1)

隐式类型转换:当您将变量定义为无符号并将其与负数进行比较时,该负数将隐式进行类型转换。正如我们所知,负数存储在两个恭维中,所以-1实际上变成了一个非常大的正数。现在,无论您提供的大数字,它总是会少于那个大数字,这就是为什么你总是得到负面答案的原因。

可能的解决方案:使用三元运算符来处理+和 - 数字。 谢谢

答案 2 :(得分:0)

输出是因为您声明了sum变量,您将其声明为unsigned sum只需将unsigned sum更改为signed sumint sum

答案 3 :(得分:0)

启用一组合理的警告后,一个好的编译器会突出显示问题:

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");
          ^

总是很好的建议,尽可能多地发出警告;由于历史原因,大多数编译器都会发出很少的警告,除非你记得要求它们。

请注意,如果您将比较更改为if (sum >= 0),那么您将获得不同(可能更有用)的消息,因为文字0可被视为0u }:

42362568.c:19:10: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]
    if(sum>=0) printf("non negative\n");
          ^~

答案 4 :(得分:0)

当我们尝试比较变量的两个不同(相同数据类型)符号时,编译器隐式(内部)将两个变量视为更高的有符号类型(无符号类型)。

听到if(sum > -1)是您的代码。您正在尝试比较unsigned sum , signed constant,因此编译器会在内部转换-1 as unsigned。 如果我们将整数大小视为2个字节,那么sum = 1(as your code),但-1 will be converted to unsigned value 65535 (do 2's compliment for -1) 现在您的代码将简化为if(sum > 65535),因此条件为FALSE,这就是为什么只有您总是得到不期望的结果。如果您想避免此问题,请始终比较相同的签名类型变量(如果两个变量都是相同的数据类型,否则不同的签名类型也没有问题。)

答案 5 :(得分:-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)(此值为65535)

您的代码中的此值为replacing with -1