以下程序应打印数组元素的总和是正数还是负数:
#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
为什么我会得到这个输出?
答案 0 :(得分:1)
在表达式sum > -1
中,通常的算术转换(“平衡”)适用。由于一个操作数为unsigned int
而另一个为int
,因此-1
的操作数int
被隐式转换为unsigned int
。比较操作在类型unsigned int
上执行。
此外,无符号变量首先永远不会保持负值,因此即使没有隐式转换,表达式也没有任何意义。
答案 1 :(得分:1)
隐式类型转换:当您将变量定义为无符号并将其与负数进行比较时,该负数将隐式进行类型转换。正如我们所知,负数存储在两个恭维中,所以-1实际上变成了一个非常大的正数。现在,无论您提供的大数字,它总是会少于那个大数字,这就是为什么你总是得到负面答案的原因。
可能的解决方案:使用三元运算符来处理+和 - 数字。 谢谢
答案 2 :(得分:0)
输出是因为您声明了sum
变量,您将其声明为unsigned sum
只需将unsigned sum
更改为signed sum
或int 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
。