这是代码:目标是判断所有阵列成员的总和是正数还是负数。我知道unsigned int是一个错误,因为我想看看它会打印什么。所以问题是为什么它打印为负数,我的意思是,对unsigned 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;
}
答案 0 :(得分:1)
签名和未签名之间的区别仅在于开发人员。对于计算机而言,数字只是在遇到PC(程序计数器)恰好指向的内存中的某些位模式时应用某些规则的位模式。
因此,如果将-1
分配给16位变量,则内存中的位模式将为1111 1111 1111 1111
(每个位都为1
- 我对32位太懒变量),无论变量是有符号还是无符号。
编译器应该抱怨条件sum > -1
,因为比较没有意义。
作为一个人,你期望sum
总是正面的,所以条件总是正确的。
但编译器将-1
转换为无符号(见下文),然后进行比较。 -1
为您提供了可以为给定位数表示的最大可能无符号数 - &gt;比较总是错误的,因为没有什么可能更大。
所以你总是得到negative
作为输出,因为头脑中的模型是错误的。
根据C99:在类型大小相同的二进制表达式中,有符号值将转换为无符号。如果有符号值无法用无符号类型表示(例如-1),那么“通过重复加或减一个可以在新[无符号]类型中表示的最大值来转换该值,直到该值为止新类型的范围。“
Kudos转到JeremyP
答案 1 :(得分:1)
由于“sum”是无符号类型,“-1”也被转换为无符号类型(见下文)。这导致与之相比的数量非常大(取决于机器的大小)。
所以在纸上尝试这种转换:
-1到二进制数(尝试使用2个字节),然后将该二进制数转换为无符号数。确切的数字取决于机器(在您的int大小上),但基本上您将总和与非常大的数字进行比较,从而得出您所看到的结果。
委员会草案 - 2011年4月12日
6.3.1.8通常的算术转换
首先,如果任一操作数的相应实数类型是long double,则另一个 操作数在不更改类型域的情况下转换为对应的实类型为long double的类型。
否则,如果任一操作数的相应实数类型是double,则另一个 操作数在不更改类型域的情况下转换为其类型的类型 相应的实际类型是双倍。
否则,如果任一操作数的相应实数类型是float,则另一个 操作数在不更改类型域的情况下转换为其类型的类型 对应的实类型是浮点数。 62)
否则,将对两个操作数执行整数提升。那么 以下规则适用于提升的操作数: 如果两个操作数具有相同的类型,则不需要进一步转换。
否则,如果两个操作数都有有符号整数类型或两者都有无符号 整数类型,具有较小整数转换等级类型的操作数是 转换为具有更高等级的操作数的类型。
相关部分:
否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则带有符号整数类型的操作数将转换为具有无符号整数类型的操作数的类型。 / p>
否则,如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数将转换为带有符号整数的操作数的类型类型。
否则,两个操作数都将转换为无符号整数类型,对应于带有符号整数类型的操作数类型。
答案 2 :(得分:0)
2的补码表示为1111 1111 1111 1111(假设无符号的大小为2个字节) 等于65535
在你的情况下,你将你的结果与65535进行比较,因为总和是&lt; 65535你得印的是负片。