C 如果我们将负整数赋给无符号整数,会发生什么

C 如果我们将负整数赋给无符号整数,会发生什么,c,C,代码如下:目标是判断数组的所有成员之和是正还是负。我知道unsigned int是一个错误,因为我想看看它将打印什么。所以问题是为什么它打印负数,我的意思是,负int到无符号int的赋值是什么 #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

代码如下:目标是判断数组的所有成员之和是正还是负。我知道unsigned int是一个错误,因为我想看看它将打印什么。所以问题是为什么它打印负数,我的意思是,负int到无符号int的赋值是什么

#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;
}
#包括
#定义ARR_尺寸5
int main(){
int数组[ARR_SIZE]={1,-2,3,4,-5};
无符号和;
int i;
对于(i=0,sum=0;i-1)打印F(“非负数”);
else printf(“负片”);
返回0;
}

有符号和无符号的区别完全在开发人员的头脑中。对于计算机来说,数字只是位模式,当它遇到PC(程序计数器)恰好指向的内存中的某些位模式时,某些规则会应用到这些位模式

因此,如果将
-1
赋值给一个16位变量,那么内存中的位模式将是
1111111111111111
(每个位都是
1
-对于32位变量,我太懒了),不管变量是有符号的还是无符号的

编译器应该抱怨条件
sum>-1
,因为比较没有意义

作为一个人,你期望总和总是正的,所以条件总是真的

但是编译器将
-1
转换为无符号(见下文),然后进行比较
-1
为给定位数提供可能代表的最大无符号数->比较始终为false,因为没有比这更大的值

因此,您总是将
负值
作为输出,因为您头脑中的模型是错误的

根据C99:在类型大小相同的二进制表达式中,有符号值转换为无符号值。如果有符号值不能在无符号类型中表示(例如-1),则“通过反复加上或减去新[unsigned]类型中可以表示的最大值的一个值来转换该值,直到该值在新类型的范围内。”


值得称道的是

2的-1补码表示为1111111111111111111(假设无符号的大小为两个字节) 等于65535

在本例中,您将结果与65535进行比较,因为sum小于65535,所以打印结果为负数。

因为“sum”是无符号类型,-1”也会转换为无符号类型(见下文)。这导致与之相比的数字非常大(多大取决于机器)

因此,请在纸上尝试这种转换:

-1转换为二进制数(尝试仅使用2个字节),然后将该二进制数转换为无符号数。确切的数字取决于机器(取决于整型大小),但基本上是将总和与一个非常大的数字进行比较,因此可以看到结果

委员会草案-2011年4月12日

6.3.1.8常用算术转换

首先,如果其中一个操作数的对应实数类型为长双精度,则另一个操作数 操作数在不改变类型域的情况下被转换为相应实型为长双精度的类型

否则,如果任一操作数的对应实数类型为双精度,则另一个操作数 操作数在不更改域类型的情况下转换为 对应的实数类型是double

否则,如果其中一个操作数的对应实数类型为float,则另一个操作数 操作数在不更改域类型的情况下转换为 相应的实数类型是float。(62)

否则,将对两个操作数执行整数提升。然后 以下规则应用于提升的操作数: 如果两个操作数的类型相同,则无需进一步转换

否则,如果两个操作数都具有有符号整数类型或都具有无符号整数类型 整数类型,则类型为较小整数转换秩的操作数为 已转换为具有更高秩的操作数类型

有关部分:

否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数类型的秩,则具有有符号整数类型的操作数将转换为具有无符号整数类型的操作数的类型

否则,如果带符号整数类型的操作数类型可以表示带符号整数类型的操作数类型的所有值,则带符号整数类型的操作数将转换为带符号整数类型的操作数类型

否则,两个操作数都将转换为与有符号整数类型的操作数类型相对应的无符号整数类型


无符号整数溢出是根据模2定义的
CHAR\u BIT*sizeof(Unsigned)
。将负值赋给无符号变量的可能性是不寻常的。在这种情况下发生的隐式转换完全由C语言定义。根据模运算规则,将该值带入目标无符号类型的范围。模等于2^N,其中N是无符号收件人中的值位数。这就是C语言中的情况。编译器应该发出一个警告,表明您正在比较第
行if(sum>-1)
处不同符号的表达式(
-1
具有类型
int
,并且
sum
是一个
无符号int
)。如果没有,请在进一步努力之前找到如何启用此警告。实际上,
sum>-1
有一个定义明确的含义,只是它不太可能是程序员的意思。这不是一种非此即彼的情况。@PascalCuoq:是的,但这会让人更难理解。你认为说这是两种可能性中的一种比说只有一种可能发生更简单吗?你的答案很模糊,“非此即彼”
sum
总是posi