无符号整数和无符号字符保持相同的值但行为不同为什么?

为什么这样呢?

unsigned char k=-1 if(k==-1) 

是假的

 unsigned int k=-1 if(k==-1) 

是真的

出于演示的目的,我们假设8位char和32位int

 unsigned char k=-1; 

k被赋值为255。

 if(k==-1) 

==运算符的左侧是unsigned char 。 右边是一个int 。 由于unsigned char所有可能值都可以放在int ,因此左侧将转换为int (这是由于整数提升而执行的,如下所述)。 这导致比较(255 == -1) ,这是错误的。


 unsigned int k=-1 

k被赋值4294967295

 if(k==-1) 

这一次,左侧(unsigned int)不能适合int。 标准说在这种情况下,两个值都转换为unsigned int。 所以这导致比较(4294967295 == 4294967295) ,这是真的。


标准的相关引用:

整数促销:(C99,6.3.1.1p2)

如果int可以表示原始类型的所有值,则该值将转换为int; 否则,它将转换为unsigned int。

通常的算术转换:(6.3.1.8)。

[对于整数操作数,]在两个操作数上执行整数提升。 然后将以下规则应用于提升的操作数:
– 如果两个操作数具有相同的类型,则不需要进一步转换。

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

C11标准草案的§6.3.1.1p2(n1570.pdf):

如果int可以表示原始类型的所有值(由宽度限制,对于位字段),该值将转换为int; 否则,它将转换为unsigned int。 这些被称为整数促销.58)整数促销不改变所有其他类型。

在第二种情况下,int不能表示unsigned int k因为它超出范围。 两个操作数最终都被转换为unsigned int并且比较相等。

由于未签名促销中没有符号扩展,因此结果不同。

unsigned char k从unsigned char(value = 255)提升为int(value = 255)。

unsigned int k的情况下,-1从int(value = -1)提升为unsigned int(value = 2 ^ 32-1)。

 unsigned char k = -1; 

-1是int类型的整数文字,相当于signed int 。 当您将较大的有符号整数分配给较小的无符号类型时,结果将以未定义的方式截断,C标准不保证会发生什么。

在C标准之外的现实世界中,这是最有可能的(假设32位CPU,两个补码):

-1是0xFFFFFFFF。 0xFFFFFFFF的最低有效字节将分配给kk == 255 。 尝试使用printf("%u")打印它并自己查看。

unsigned int k=-1的情况下,-1仍然是signed int。 但是当它存储在k时,它会被隐式(无声地)提升为unsigned int。 当您稍后比较k == -1 ,右侧-1将再次升级为无符号类型,并将与存储在k的数据进行比较。