无符号类型和有符号类型的等式运算行为差异

4
可能重复:有符号/无符号比较 下面的代码将无符号整数设置为负数,然后将其与相同的负数进行比较。我得到的输出是“不相等”。我知道当将无符号整数设置为-1时,在这种情况下,无符号整数的值设置为255。
#include <stdint.h>
#include <iostream>

int main(int argc, char **argv)
{
  uint8_t test = 0;
  int8_t set = -1;

  test = set;

  if (test == set) {
    std::cout << "Equal";
  } else {
    std::cout << "Not Equal";
  }
}

然而,是什么导致了等号运算符返回false呢?这似乎与类似问题Signed/unsigned comparisons的答案相矛盾,其指出:

许多二元运算符都期望算术或枚举类型的操作数,并以类似的方式进行转换并产生结果类型。其目的是产生一个共同的类型,也是结果的类型。这种模式称为通常的算术转换,其定义如下:

如果任一操作数的类型为long double,则另一个操作数应转换为long double。

否则,如果任一操作数为double,则另一个操作数应转换为double。

否则,如果任一操作数为float,则另一个操作数应转换为float。

否则,应对两个操作数执行整数提升(4.5)。54)

然后,如果任一操作数为unsigned long,则另一个操作数应转换为unsigned long。

否则,如果一个操作数为long int,另一个操作数为unsigned int,则如果long int可以表示unsigned int的所有值,则unsigned int应转换为long int;否则,两个操作数都应转换为unsigned long int。

否则,如果任一操作数为long,则另一个操作数应转换为long。

否则,如果任一操作数为unsigned,则另一个操作数应转换为unsigned。

因此,根据这个答案,既然两个操作数都是unsigned,则另一个操作数应转换为unsigned,等式应该通过。但很明显它没有通过,并且如在这个问题中已经回答的那样,它们都被提升为signed ints。


-Wall -Werror 会告诉你问题所在。你在类型比较中出现了有符号/无符号不匹配的情况。 - WhozCraig
@larsmans - 很容易忽略赋值 test = set。 <g> - Pete Becker
小心使用标准库名称作为变量,例如 set - Mark B
@WhozCraig - 我知道代码是错误的,我只是在询问行为背后的基本规则。 - umps
1个回答

9

这确实是标准行为。在使用 == 和其他大部分运算符时,小于 int 的类型将被提升为 int。因此,test 被提升为值为 255 的 int。而 set 也被提升为 int,但它是一个负数,因此它的值,在提升之前和之后都是 -1。由于 255 不等于 -1,所以比较结果为 false

经验教训是:如果在比较中混合使用有符号和无符号类型,请小心。


谢谢你的回答,这似乎与使用无符号整数和有符号整数进行比较的情况相矛盾。我的问题是为什么会不同? - umps
在编程中,对于无符号类型,存在一些无法表示为相应有符号类型的值,反之亦然。因此,对于大于或等于int大小的类型,所采用的提升规则也有所不同。 - Pete Becker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接