【问题标题】:Unsigned integer and unsigned char holding same value yet behaving differently why?无符号整数和无符号字符具有相同的值但行为不同,为什么?
【发布时间】:2013-05-27 11:11:30
【问题描述】:

为什么会这样

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

是假的

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

是真的

【问题讨论】:

  • unsigned 代表>=0
  • 它可以编译,但是 Dev-C++ 说:[Warning] comparison is always false due to limited range of data type
  • 你应该先打印价值,然后再确定它拥有什么价值以及价值是如何存储的
  • 我使用代码块我猜它使用 Gcc
  • @AnkitBanerjee 你知道他们可能没有持有相同的价值,对吧?

标签: c


【解决方案1】:

为了演示的目的,我们假设 8 位 chars 和 32 位 ints。

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)

这一次,左侧(无符号整数)不能放入整数。标准规定,在这种情况下,两个值都转换为无符号整数。所以这导致比较(4294967295 == 4294967295),这是真的。


标准中的相关引用:

整数提升:(C99, 6.3.1.1p2)

如果一个int可以表示原始类型的所有值,则将该值转换为一个int;否则,将其转换为无符号整数。

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

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

【讨论】:

  • 也许你可以留下标准 6.3.1.3 的报价。
  • 我添加了与促销和转化相关的标准报价,这是这里的核心问题。 6.3.1.3 描述从有符号转换为无符号时会发生什么,这也是相关的,但我认为确切的规则在这里不太重要,所以我不会引用它。
【解决方案2】:

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

如果一个 int 可以表示原始类型的所有值(受限制 通过宽度,对于一个位域),该值被转换为一个 int; 否则,将其转换为无符号整数。这些被称为 整数促销.58) 所有其他类型都不会被整数改变 促销活动。

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 不,unsigned int 永远不会提升为 int。在这种情况下,int 被转换为 unsigned int
    【解决方案4】:
    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 中的数据进行比较。

    【讨论】:

    • 根据C标准,“在新类型中可以表示的最大值的基础上反复加减1,直到值在新类型的范围内。 "
    猜你喜欢
    • 2011-11-02
    • 2019-03-16
    • 1970-01-01
    • 1970-01-01
    • 2015-04-07
    • 2022-01-20
    • 2021-07-30
    • 2013-10-28
    相关资源
    最近更新 更多