【问题标题】:Why is unsigned 4 not considered greater than signed -2? [duplicate]为什么不认为无符号 4 大于有符号 -2? [复制]
【发布时间】:2018-05-01 06:57:23
【问题描述】:
unsigned int x = 4;
int y = -2; 
int z = x > y; 

在实现这个操作时,变量Z的值为0,但为什么是0而不是1呢?

【问题讨论】:

  • 学习算术提升!!
  • > 比较unsignedint --> (i < 0 || u > i)

标签: c unsigned signed comparison-operators


【解决方案1】:

信不信由你,如果一个 C 表达式由两个参数组成,一个是 int 类型,另一个是 unsigned 类型,那么 int 值是提升在进行比较之前转换为 unsigned 类型。

因此,在您的情况下,y 被提升为 unsigned 类型。因为它是负数,所以它会通过添加UINT_MAX + 1 来转换,它会假定一个值UINT_MAX - 1

因此x > y 将为 0。

是的,这是很多错误的原因。即使是专业程序员也不时会为此而堕落。一些编译器会警告你:例如,使用 gcc,如果你使用-Wextra 编译,你会得到一个警告。

【讨论】:

  • 补充一点:这种行为的根本原因是,CPU 指令集通常不包含用于混合符号比较的命令。如果没有硬件支持,正确实现混合符号比较将非常棘手/缓慢。当然,CPU 设计人员可以提供这样的指令,但出于某种原因,他们从来没有想过这样做。至少在 C 成为低级编程的事实标准之前,他们没有这样做。现在,由于 C 以它的方式定义了比较,因此如果实现了混合符号比较命令,则不会使用它们......
  • @cmaster:更根本的原因是不同的编译器在标准之前的日子里做了不同的事情,标准的作者想要编写一个尽可能接近拟合的单一规则商场。我不认为任何从头开始设计语言的人都会按原样编写规则。
  • @supercat 好吧,从语言的角度来看,混合符号比较将是自然的、单一的规则选择:只需将两个操作数都输入它们的类型并比较它们的逻辑值。 (unsigned char)128 > (signed char)-1。简单,不足为奇,有用。问题是,CPU 没有提供这样的比较,编译器不能使用 CPU 不提供的东西。 C 被设计为在当时的 CPU 上运行得很快,因此它并没有做自然、简单、合乎逻辑的事情,而是针对 CPU 实际提供的功能,并专门添加了规则以避免混合符号比较 i>.
  • @cmaster:问题在于语言将除<<>> 之外的所有双操作数整数运算符的行为指定为将两个操作数转换为通用类型,并产生以下结果该类型或始终为int 类型的结果。 CPU行为与它无关。如果标准规定< 应该比较数字操作数而不考虑类型,而不平衡提升,那么编译器通常不会特别难以合理有效地处理。不需要处理一个操作数为...的两种情况的代码...
  • ...在其他范围之外可以借助强制转换更有效地编译,但在具有 16 位 int 的典型系统上,生成高效的逻辑正确代码机器为int1 > uint1 生成同样高效的机器代码为(long)int1 > (long)uint1 更容易。
【解决方案2】:

称为整数提升。

int z = x > y; 

在此示例中,comparison(>) 运算符signed intunsigned int 进行操作。根据转换规则,y 被转换为无符号整数。因为-2 不能表示为无符号整数值,所以-2 被转换为-2 + UINT_MAX+1

C11 6.3.1.3,第 2 段:

否则,如果新类型是无符号的,则值转换为 反复加或减一大于最大值 可以用新类型表示,直到值在 新类型。

所以,程序打印0,因为UINT_MAX 不小于4

或者

如果要打印 1,则执行显式类型大小写。喜欢:

int z =  (int)x >y; 

【讨论】:

    【解决方案3】:

    这是算术转换的结果。

    在表达式x > y 中,有一个int 操作数和一个unsigned int 操作数。 y 提升为unsigned int,将y 的值加上unsigned int 的最大值加1 转换的值。

    C standard 涉及算术转换的第 6.3.1.8 节规定如下:

    许多期望算术类型的操作数的运算符导致 转换和产生结果类型以类似的方式。目的是为了 确定操作数和结果的通用实数类型。为了 指定操作数,每个操作数都被转换,不改变类型 域,对应的实数类型是共同实数的类型 type. 除非另有明确说明,否则常见的实数类型也是 结果的对应实类型,其类型域为 操作数的类型域(如果它们相同且复杂) 否则。这种模式称为通常的算术转换

    ...

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

    所以现在y 是一个非常大的值,与x(4)进行比较。由于x 小于此值,x > y 的计算结果为 false,其值为 0。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-17
      • 2012-11-16
      • 2019-03-16
      • 2015-05-11
      • 2011-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多