2013-05-27 32 views
3

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

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

是假的,因为在未签名的推广没有符号扩展的结果是不同模式

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

是真的

+0

'unsigned'代表'> = 0' –

+0

它编译,但Dev-C++说:'由于数据类型范围有限,[Warning]比较始终是false' – johnchen902

+0

u应该在打印值之前确定它是什么它保存的价值和价值如何存储 –

回答

0

unsigned char k从无符号字符(值= 255)提升为int(值= 255)。

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

+3

不,无符号整型不会被提升为int。这是在这种情况下被转换为'unsigned int'的int。 –

+0

谢谢丹尼尔,我已经纠正了我的答案。 –

19

为了演示的目的,我们假设8位char s和32位int s。

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) 

这一次,左手侧(无符号整数)可以不是int内配合。标准说在这种情况下,两个值都被转换为无符号整数。所以这导致比较(4294967295 == 4294967295),这是事实。


从标准相关报价:

整数优惠:(C99,6.3.1.1p2)

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

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

[对于整数操作数],整数提升在两个操作数上执行。然后将下列规则应用于提升的操作数:
- 如果两个操作数具有相同类型,则不需要进一步转换。
...
- 否则,如果具有无符号整数类型的操作数的级别大于或等于其他操作数的类型的级别,则带有 有符号整数类型的操作数将转换为无符号的操作数的类型 integer类型。
...

+1

也许你可以留下标准6.3.1.3的报价。 –

+0

我添加了与促销和转化有关的标准报价,这是这里的核心问题。 6.3.1.3描述从签名转换为无符号时会发生什么,这也是相关的,但我认为确切的规则在这里不太重要,所以我不会引用它。 – interjay

+0

+1是的,你的答案是完整的AFAIK。 –

0
unsigned char k = -1; 

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

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

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

unsigned int k=-1的情况下,-1仍然是一个有符号整数。但是当它存储在k中时,它会隐含地(静默地)提升为一个无符号整数。当您稍后比较k == -1时,右侧-1将再次升级为无符号类型,并且将与存储在k中的数据进行比较相等。

+2

根据C标准,“通过重复添加或者减去比新型 中可以表示的最大值多一个值,直到该值在新类型的范围内,该值被转换。” – Sebivor

1

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

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

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

相关问题